简体   繁体   中英

How to bind a constructor in C++?

Needless to over explain. The following code is self-evident:

struct X
{
    X(int n){}
};

int main()
{
    std::vector<int> src;
    std::vector<X>   dest;

    // Below is not valid in current C++, but that is just what I want.
    transform(src.begin(), src.end(), back_insert(dest), std::bind(&X::X, _1)); 
}

A constructor takes some arguments and returns an object of the class of the constructor.

A constructor looks like a function, acts like a function, and is exactly a function.

So, I think std::bind should uniformly treat constructors and other callable objects.

However, how can I extend the function template "bind" to implement that?

Since X is implicitly constructible from int , a simple copy should achieve the conversion.

copy(src.begin(), src.end(), std::back_inserter(dest)); 

Or even using the vector's constructor:

std::vector<X>   dest(src.begin(), src.end());

In the general case, boost's lambda library has a constructor functor.

#include <boost/lambda/bind.hpp>
#include <boost/lambda/construct.hpp>
...
using namespace boost::lambda;
transform(src.begin(), src.end(), std::back_inserter(dest), bind(constructor<X>(), _1));

In this particular case binding might not be necessary, since there is only one argument to constructor.

I don't know if there are cooler Boost ways, but you could write something like this:

class Builder
{
    X operator() (int value) const { return X(value); }
};

transform(src.begin(), src.end(), back_insert(dest), Builder()); 

A constructor is a member function.

A member function needs an object to be bound to.

A constructor is only called for a not-yet-existing object, so there can never be an object to bind the constructor to.

In your case, the constructor arguments (the int values from src) should go to (a possible) back_inserter that calls the non-default ctor and not to std::transform. (EDIT: this is only true for non-copy-ctor usage)

Actually, what you want to do here is to call std::copy:

std::copy(src.begin(), src.end(), std::back_inserter(dest)); 

A constructor takes some arguments and returns an object of the class of the constructor.

No, a constructor does not return anything, and there is no such thing as a pointer to a constructor.

Build a factory function. These are static member functions or stand-alone functions that also construct objects, usually after validating inputs. They're useful whenever you want to ensure your objects cannot be built with invalid input (after all, you cannot abort construction within a ctor).

Since a factory is an ordinary function, you can easily bind to it to get the same effect you appear to want- a bound function that builds objects.

class X
{
public:
   X(OtherObject a, OtherData data);
   virtual ~X() {}
};

// Factory- return "X" instead of "X*" if not using the heap
X* CreateX(OtherObject a, OtherData data) {
    /*
        Logic that checks a, data for validity...
    */
    if(invalid) {
       return 0;   // You get no object
    }
    return new X();
}

Now you just bind to "CreateX" to build objects. It is a normal function, however, not a constructor so all the normal rules for functions apply- especially those for copy and move construction of objects.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM