I'm having trouble using std::bind
with std::make_unique
.
I have an object to whose constructor I pass factory functions for making std::unique_ptr
s of objects of another class type.
Using VS2013, this works:
Tester tester(
[](){return std::make_unique<AlphaBetaSingleThreadSSE>( 0,7 ); },
[](){return std::make_unique<AlphaBetaSingleThread>( 0,7 ); },
20 );
This gives me compile errors:
Tester tester(
std::bind( std::make_unique<AlphaBetaSingleThreadSSE>,0,7 ),
std::bind( std::make_unique<AlphaBetaSingleThread>,0,7 ),
20 );
The error messages state:
error C2512: 'AlphaBetaSingleThread' : no appropriate default constructor available
error C2512: 'AlphaBetaSingleThreadSSE' : no appropriate default constructor available
Why does the std::bind
approach fail?
std::make_unique
is defined as follows:
§ 20.8.1.4 [unique.ptr.create]
template <class T, class... Args> unique_ptr<T> make_unique(Args&&... args);
1 Remarks: This function shall not participate in overload resolution unless
T
is not an array.2 Returns:
unique_ptr<T>(new T(std::forward<Args>(args)...)).
By explicitly instantiating this function template with std::make_unique<AlphaBetaSingleThreadSSE>
you end up with the following specialization:
std::unique_ptr<AlphaBetaSingleThreadSSE> make_unique()
{
return std::unique_ptr<AlphaBetaSingleThreadSSE>(new AlphaBetaSingleThreadSSE());
}
That is, it won't anymore let you pass additional arguments that would be forwarded to the constructor of AlphaBetaSingleThreadSSE
, and instead, will try to use a default constructor of AlphaBetaSingleThreadSSE
(which doesn't exist as the error message states).
You can work around that by specifying also type template parameter Args
:
std::make_unique<AlphaBetaSingleThreadSSE, const int&, const int&>
but then you won't benefit from perfect-forwarding and this is not a portable solultion anyway. A better solution is to stay with a lambda.