c++ - 更改构造函数优先级

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

}

最佳答案

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

调用(a)不需要转换;参数类型 DerivedVariantBT = 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;
}

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

关于c++ - 更改构造函数优先级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5720539/

相关文章:

c++ - 二次公式 c++ - 用户定义的函数

c++ - C++ 中命名空间别名的范围是什么?

c++ - C++ 中包装器类的大小写相关可变性(例如 uint8_t 数组包装器)

java - 这是一个什么样的构造函数,以 <T extends Drawable & DrawerToggle> 开头?

c++ - 如何避免调用 vector 中元素的复制构造函数

c++ - 用于多态性的引用和指针?

c++ - 将包含 int 和 float 的 4 个字节的数据转换为 float

c++ - 可调用到 std::bind 的类型

c++ - 使用模板函数设计分层类

c++ - sfinae 上下文中的模板变量