Olu*_*ide 3 c++ templates constructor-overloading sfinae c++11
为什么以下尝试重载构造函数Foo::Foo失败?此外,我很欣赏替代方案/解决方法
#include <vector>
#include <type_traits>
namespace xyz
{
struct MemoryManager{};
template<typename T , typename Alloc=MemoryManager>
class vector
{
};
}
template<typename T, template<typename,typename> class V , typename A>
struct Foo
{
template<typename U = T ,
typename Dummy = typename std::enable_if<
std::is_same<std::vector<U>, V<U,A> >::value >::type >
Foo() // when instantiated with the std vector
{
}
template<typename U = T ,
typename Dummy = typename std::enable_if<
std::is_same<xyz::vector<U>, V<U,A> >::value >::type >
Foo() // when instantiated with my custom vector
{
}
};
int main()
{
}
Run Code Online (Sandbox Code Playgroud)
错误信息:
23:3: error: ‘template<class T, template<class, class> class V, class A> template<class U, class Dummy> Foo<T, V, A>::Foo()’ cannot be overloaded
Foo() // when instantiated with my custom vector
18:3: error: with ‘template<class T, template<class, class> class V, class A> template<class U, class Dummy> Foo<T, V, A>::Foo()’
Foo() // when instantiated with the std vector
Run Code Online (Sandbox Code Playgroud)
您不能以这种方式重载构造函数,因为默认参数不是签名的一部分.实际上,你有:
template <typename, typename>
Foo();
template <typename, typename>
Foo();
Run Code Online (Sandbox Code Playgroud)
这个规则可能在模板世界之外更清晰,这两个函数不能相互重载:
void foo(int x = 42);
void foo(int y = 17);
Run Code Online (Sandbox Code Playgroud)
您可以改为将第二个模板参数设为默认的非类型参数,以便两个构造函数具有不同的签名:
template<typename U = T ,
std::enable_if_t<std::is_same<std::vector<U> , V<T,A> >::value, int> = 0>
Foo() // when instantiated with the std vector
Run Code Online (Sandbox Code Playgroud)
或者您可以使用虚拟类型委托两个构造函数:
template <typename T> struct tag { };
Foo()
: Foo(tag<V<T,A>>{})
{ }
Foo(tag<std::vector<T>> )
{ /* std vector */ }
Foo(tag<xyz::vector<T>> )
{ /* your vector */ }
Run Code Online (Sandbox Code Playgroud)