使用普通的复制构造函数传递类对象,但没有输出?

Joh*_*itb 8 c++ ellipsis language-lawyer c++11

我和GCC和Clang一起尝试了这个程序,但两者都没有输出

#include <iostream>

struct A {
  A(){}

  template<typename T>
  A(T &) {
    std::cout << "copied!";
  }
};

void f(...) { }

int main() {
  A a;
  f(a);
}
Run Code Online (Sandbox Code Playgroud)

根据我的标准阅读,该程序应该输出"copied!".任何人都可以告诉我,我是否错了,或者这是否是这两个编译器中的错误?

Nic*_*las 3

看起来您所期望的是标准定义的行为。

模板函数不会阻止创建复制构造函数/赋值运算符。因此,模板函数不会阻止类被视为“可简单复制”。但是,当实际复制它们时,它们确实会参与重载决策,因此它们可能会产生干扰。并且由于a在此示例中是非常量左值,因此它A(A&)比它更适合签名A(const A&)。所以它调用了模板函数。

(尽管我不明白为什么你不费心在你的问题中解释所有这些,因为你显然做了你的研究。)

然而,考虑到这是一个多么小的极端情况,我不会依赖这种行为来强制可平凡复制的类不被平凡复制。

  • 这是错误的。模板化构造函数不是复制构造函数,不会妨碍在传递相同类类型的非常量左值时调用它。 (3认同)
  • 如果像你们这样的两位专家不能就标准的内容达成一致,在我看来,这强烈表明存在需要澄清的标准问题。请联系 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html 的作者帮助我们澄清此问题。 (3认同)
  • @Xeo:不,但是如果还有一个合成的[非模板]复制构造函数,并且具有相同的签名,那么它将在重载解析中获得优先权。这个模板“复制构造函数”甚至永远不会被实例化! (2认同)
  • 我不是语言专家,但我阅读 [class.copy]/p9 的方式是,在这个示例中,编译器生成的“A”复制构造函数具有签名“A(const A&amp;)”。因此,在本例中,它与模板化的“A(T&amp;)”构造函数的匹配较差(由于 [over.match] 中的规则,我目前懒得缩小范围到更具体的部分)。 (2认同)