可变构造函数是否应该隐藏隐式生成的构造函数?

时间:2010-06-01 21:49:38

标签: c++ templates c++11 copy-constructor variadic-templates

variadic构造函数是否应该隐藏隐式生成的构造函数,即默认构造函数和复制构造函数?

struct Foo
{
    template<typename... Args> Foo(Args&&... x)
    {
        std::cout << "inside the variadic constructor\n";
    }
};

int main()
{
    Foo a;
    Foo b(a);
}

不知何故,我希望在阅读this answer之后不打印任何内容,但它会在g ++ 4.5.0上打印inside the variadic constructor两次:(这种行为是否正确?


没有可变参数模板也会发生:

struct Foo
{
    Foo()
    {
        std::cout << "inside the nullary constructor\n";
    }

    template<typename A> Foo(A&& x)
    {
        std::cout << "inside the unary constructor\n";
    }
};

int main()
{
    Foo a;
    Foo b(a);
}

同样,两行都被打印出来。

1 个答案:

答案 0 :(得分:21)

隐式声明的复制构造函数的声明实际上并未被抑制。由于重载决策的规则,它只是没有被调用。

隐式声明的复制构造函数的格式为Foo(const Foo&)。这个的重要部分是它需要一个const引用。您的构造函数模板采用非const引用。

a不是const,因此非const用户声明的构造函数模板优先于隐式声明的复制构造函数。要调用隐式声明的复制构造函数,可以使a const:

const Foo a;
Foo b(a);

或者您可以使用static_cast获取对a

的const引用
Foo a;
Foo b(static_cast<const Foo&>(a));

描述这种情况的重载决策规则主要在C ++ 0x FCD的§13.3.3.2/ 3中找到。这个特殊的场景,结合了左值和右值引用,有点像第303页的各种例子所描述。


可变参数构造函数模板将抑制隐式声明的默认构造函数,因为可变参数构造函数模板是用户声明的,并且只有在没有用户声明的构造函数时才提供隐式声明的默认构造函数(C ++ 0xFCD§12.1/ 5) ):

  

如果类X没有用户声明的构造函数,则没有参数的构造函数被隐式声明为默认值。

可变参数构造函数模板不会抑制隐式声明的复制构造函数,因为只有非模板构造函数可以是复制构造函数(C ++ 0xFCD§12.8/ 2,3和8):

  

如果第一个参数的类型为XX&const X&volatile X&,则类const volatile X&的非模板构造函数是一个复制构造函数,并且没有其他参数,或者所有其他参数都有默认参数。

     

X的非模板构造函数是移动构造函数,如果其第一个参数的类型为X&&const X&&volatile X&&const volatile X&& ,并且没有其他参数,或者所有其他参数都有默认参数。

     

如果类定义没有显式声明复制构造函数并且没有用户声明的移动构造函数,则隐式声明复制构造函数为默认值。