I'm doing some template-meta-programming and I would like to implement a generic cloning function that selects a method of cloning depending on the validity of expressions via SFINAE (Substitution Failure Is Not An Error).
On this reference website it says that
The function
make_unique<T>( std::forward<Args>(args)... )
is equivalent to:
unique_ptr<T>(new T(std::forward<Args>(args)...))
Does this mean that the following code
template <typename T>
auto my_clone( const T & t ) -> decltype( std::make_unique<T>(t) )
{
return std::make_unique<T>(t);
}
should be completely equivalent to
template <typename T>
auto my_clone( const T & t ) -> decltype( std::unique_ptr<T>( new T(t) ) )
{
return std::unique_ptr<T>( new T(t) );
}
even when I have other overloads of the function my_clone
? In other words: is std::make_unique()
SFINAE-friendly?
If T
is not copy constructible, then the latter code would not participate in overload resolution due to SFINAE.
Here's a small example that fails to compile on GCC 5.3 with C++14 turned on:
#include <memory>
// It does **not** work with this snippet:
template <typename T>
auto my_clone( const T & t ) -> decltype( std::make_unique<T>( t ) )
{
return std::make_unique<T>( t );
}
/* // But it works with this snippet instead:
template <typename T>
auto my_clone( const T & t ) -> decltype( std::unique_ptr<T>( new T(t) ) )
{
return std::unique_ptr<T>( new T(t) );
}*/
// This is another overload for testing purposes.
template <typename T>
auto my_clone( const T & t ) -> decltype(t.clone())
{
return t.clone();
}
class X
{
public:
X() = default;
auto clone() const
{
return std::unique_ptr<X>( new X(*this) );
}
private:
X( const X & ) = default;
};
int main()
{
// The following line produces the compiler error:
// "call to 'my_clone' is ambiguous"
const auto x_ptr = my_clone( X() );
}
Aucun commentaire:
Enregistrer un commentaire