cyt*_*nox 4 c++ templates constructor overload-resolution
是否可以为所有派生类型和模板构造函数定义构造函数?我写了这个测试用例来说明我的问题:
#include <iostream>
class Variant;
class CustomVariant;
class Variant
{
public:
Variant(void)
{}
Variant(const Variant&)
{
std::cout << "ctor" << std::endl;
}
Variant(const CustomVariant&)
{
std::cout << "custom" << std::endl;
}
template<typename T>
Variant(const T&)
{
std::cout << "template" << std::endl;
}
};
class CustomVariant : public Variant
{
};
class DerivedVariantA : public CustomVariant
{
};
class DerivedVariantB : public CustomVariant
{
};
int main(void)
{
DerivedVariantB dvb;
Variant v(dvb);
// expcected output: "custom" instead of "template"
}
Run Code Online (Sandbox Code Playgroud)
template <typename T> Variant(const T&) // (a)
Variant(const CustomVariant&) // (b)
Run Code Online (Sandbox Code Playgroud)
呼叫(a)不需要转换; 参数类型,DerivedVariantB是完全匹配的地方T = DerivedVariantB.
调用(b)需要派生到基础的转换.因此,(a)是比(b)更好的匹配.
如果使用类型的参数调用构造函数CustomVariant,则两个构造函数都是完全匹配,因此选择(b)因为其他条件相同,所以非模板优先于模板.
您可以通过使用以下内容来禁止使用模板T来源:Variantstd::enable_if
template<typename T>
Variant(const T&,
typename std::enable_if<
!std::is_base_of<Variant, T>::value, void*
>::type = 0)
{
std::cout << "template" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
这使得模板在T派生时不可实例化Variant,因此在重载解析期间不可用. enable_if并且is_base_of是C++ 0x中C++的新手,您的编译器和标准库可能会支持它们.如果没有,您也可以在C++ TR1或Boost.TypeTraits中找到它们.