更改构造函数优先级



是否可以为所有派生类型定义一个构造函数和一个模板构造函数?我写了这个测试用例来说明我的问题:

#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"
}
template <typename T> Variant(const T&)  // (a)
Variant(const CustomVariant&)            // (b)

调用(a)不需要转换;参数类型DerivedVariantB是精确匹配的,其中T = DerivedVariantB .

调用(b)需要一个派生到基的转换。因此, (a) 是一个更好的匹配比 (b)

如果使用CustomVariant类型的参数调用构造函数,则两个构造函数都是精确匹配的,因此选择(b),因为在其他条件相同的情况下,非模板优于模板。

您可以通过使用std::enable_if:

来抑制使用T派生自Variant的模板。
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;
}

这使得当TVariant派生时模板不可实例化,因此在重载解析期间它将不可用。enable_ifis_base_of是c++在c++ 0x中的新特性,您的编译器和标准库可能支持它们。如果没有,你也可以在c++ TR1或Boost.TypeTraits.

中找到它们。

不,在类中可用的构造函数列表中,没有以DerivedVariantB类型的实例作为参数的构造函数。因此将调用生成的模板。

class DerivedVariantB ; // Forward Declaration
class Variant
{
    public:
    // ...
     Variant( const DerivedVariantB &obj )
     {
         std::cout << "n DerivedVariantB n";
     }
};
现在,可以调用接受DerivedVariantB类型引用的构造函数,而不是模板生成的构造函数。

最新更新