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

fre*_*low 27 c++ templates copy-constructor variadic-templates c++11

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

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

int main()
{
    Foo a;
    Foo b(a);
}
Run Code Online (Sandbox Code Playgroud)

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


它也没有可变参数模板:

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);
}
Run Code Online (Sandbox Code Playgroud)

同样,两行都打印出来.

Jam*_*lis 21

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

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

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

const Foo a;
Foo b(a);
Run Code Online (Sandbox Code Playgroud)

或者您可以使用static_cast获取const引用a:

Foo a;
Foo b(static_cast<const Foo&>(a));
Run Code Online (Sandbox Code Playgroud)

描述这种情况的重载决策规则主要在C++ 0x FCD的§13.3.3.2/ 3中找到.这个具有左值和右值引用组合的特定场景有点由第303页的各种示例描述.


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

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

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

A类非模板的构造X是一个拷贝构造函数,如果它?第一个参数的类型为X&,const X&,volatile X&const volatile X&,并且或者有没有其他参数,否则所有其他参数默认参数.

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

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