可变参数构造函数是否应该隐藏隐式生成的构造函数?
可变参数构造函数是否应该隐藏隐式生成的构造函数,即默认构造函数和复制构造函数?
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
事实上,隐式声明的复制构造函数的声明并未被抑制。只是由于重载解析规则而没有被调用。
隐式声明的复制构造函数的形式为
Foo(const Foo&)
。其中重要的部分是它需要一个 const 引用。您的构造函数模板采用非常量引用。a
不是 const,因此非常量用户声明的构造函数模板优于隐式声明的复制构造函数。要调用隐式声明的复制构造函数,可以将a
设置为 const:或者可以使用
static_cast
获取对a
的 const 引用:描述这一点的重载解析规则主要在 C++0x FCD 的 §13.3.3.2/3 中找到。这种特定的场景,结合了左值和右值引用,可以通过第 303 页上的各种示例进行描述。
可变参数构造函数模板将抑制隐式声明的默认构造函数,因为可变参数构造函数模板是用户声明的,并且隐式声明的默认构造函数仅当没有用户声明的构造函数时才提供构造函数(C++0x FCD §12.1/5):
可变参数构造函数模板不会抑制隐式声明的复制构造函数,因为只有非模板构造函数才能成为复制构造函数(C++0x FCD §12.8/2、3 和 8):
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 makea
const:or you can use
static_cast
to obtain a const reference toa
: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):
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):