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

发布于 2024-09-04 00:18:23 字数 817 浏览 6 评论 0原文

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

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

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

不知何故,我希望在阅读 这个答案后不会打印任何内容,但它在 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);
}

同样,两行都被打印。

Are variadic constructors supposed to hide the implicitly generated ones, i.e. the default constructor and the copy constructor?

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

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

Somehow I was expecting this to print nothing after reading this answer, but it prints inside the variadic constructor twice on g++ 4.5.0 :( Is this behavior correct?


It also happens without variadic templates:

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);
}

Again, both lines are printed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

∞琼窗梦回ˉ 2024-09-11 00:18:23

事实上,隐式声明的复制构造函数的声明并未被抑制。只是由于重载解析规则而没有被调用。

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

a 不是 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++0x FCD §12.1/5):

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

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

X的非模板构造函数是一个复制构造函数,如果它的第一个参数是X&类型,const X&易失性 X&const 易失性 X&,并且要么没有其他参数,要么所有其他参数都有默认参数。

X的非模板构造函数是移动构造函数,如果它的第一个参数是X&&类型,const X&&< /code>、易失性 X&&const 易失性 X&&,并且要么没有其他参数,要么所有其他参数都有默认参数。

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


Declaration of the implicitly declared copy constructor is not, in fact, being suppressed. It's just not being called due to the rules of overload resolution.

The implicitly declared copy constructor has the form Foo(const Foo&). The important part of this is that it takes a const reference. Your constructor template takes a non-const reference.

a is not const, so the non-const user-declared constructor template is preferred over the implicitly-declared copy constructor. To call the implicitly-declared copy constructor, you can make a const:

const Foo a;
Foo b(a);

or you can use static_cast to obtain a const reference to a:

Foo a;
Foo b(static_cast<const Foo&>(a));

The overload resolution rules that describe this are found mostly in §13.3.3.2/3 of the C++0x FCD. This particular scenario, with a combination of lvalue and rvalue references, is sort of described by the various examples on page 303.


A variadic constructor template will suppress the implicitly declared default constructor because a variadic constructor template is user-declared and the implicitly declared default constructor is only provided if there are no user-declared constructors (C++0x FCD §12.1/5):

If there is no user-declared constructor for class X, a constructor having no parameters is implicitly declared as defaulted.

A variadic constructor template will not suppress the implicitly declared copy constructor because only a non-template constructor can be a copy constructor (C++0x FCD §12.8/2, 3, and 8):

A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments.

A non-template constructor for class X is a move constructor if its first parameter is of type X&&, const X&&, volatile X&&, or const volatile X&&, and either there are no other parameters or else all other parameters have default arguments.

If the class definition does not explicitly declare a copy constructor and there is no user-declared move constructor, a copy constructor is implicitly declared as defaulted.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文