更改构造函数优先级

时间:2011-04-19 17:54:36

标签: 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"

}

2 个答案:

答案 0 :(得分:6)

template <typename T> Variant(const T&)  // (a)
Variant(const CustomVariant&)            // (b)

无需转换即可致电(a);参数类型DerivedVariantBT = DerivedVariantB完全匹配。

调用(b)需要派生到基础的转换。因此,(a)(b)更好。

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

您可以使用T禁止使用Variant来自std::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;
}

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

答案 1 :(得分:0)

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

class DerivedVariantB ; // Forward Declaration

class Variant
{
    public:
    // ...

     Variant( const DerivedVariantB &obj )
     {
         std::cout << "\n DerivedVariantB \n";
     }
};

现在,可以调用带有DerivedVariantB类型引用的构造函数,而不是生成的模板。