以下内容不能用g ++ 4.4.7编译,在命令行上传递了--std == c ++ 0x:
#include#include template class A { public: T v; A() { std::cout << "A default constructor\n"; } A(const A& i): v(i.v) { std::cout << "A copy constructor\n"; } A(A&& i): v(std::move(i.v)) { std::cout << "A move constructor\n"; } #if 1 // turn this off to fix the version without static_cast template explicit A(const V& i): v(i) {} #endif }; class B: public A { public: B() { std::cout << "B default constructor\n"; } #if 1 // turn this off to get static_cast that makes it compile B(const B& i): A (i) { std::cout << "B copy constructor\n"; } B(B&& i): A (std::move(i)) { std::cout << "B move constructor\n"; } #else B(const B& i): A (static_cast &>(i)) { std::cout << "B copy constructor\n"; } B(B&& i): A (std::move(static_cast &&>(i))) { std::cout << "B move constructor\n"; } #endif }; B foo() { B t; return t; } int main() { B t(foo()); B t2(std::move(t)); std::cout << "Result is " << t2.v << std::endl; return 0; }
产生以下错误,其中复制和移动构造函数似乎调用显式A模板而不是A的明显复制/移动构造函数:
container.cpp: In constructor ‘A::A(const V&) [with V = B, T = int]’: container.cpp:26: instantiated from here container.cpp:17: error: cannot convert ‘const B’ to ‘int’ in initialization
关闭第一个#if 1
模板会删除模板,然后编译并生成预期的调用.关闭第二个#if 1
也使它工作(但是在我们的代码中做相同的操作会很痛苦,需要大量的仔细编辑).
目前我通过将模板构造函数更改为此并将bool添加到所有用户来解决此问题,但这很难看:
A(const V&i, bool dummy): v(i) {}
问题:
这是GCC中的错误吗?
如果没有,有人可以解释为什么会这样吗?
建议的修复是什么?我的static_casts是否正确?
Konrad Rudol.. 5
似乎复制和移动构造函数调用显式A模板而不是A的明显复制/移动构造函数:
没有什么明显的是关于调用A(A const&)
构造函数:你调用A
同类型的参数的构造函数B const&
,而这样做的最好的比赛简直是模板(这是一个精确匹配),而不是A(A const&)
,这是不完全匹配(它需要隐式预报).
所以这种行为完全符合预期.如果您不想这样做,请更改模板,以便在使用子类A
(通过SFINAE)调用时禁用它:
templateexplicit A(const V& i, typename std::enable_if::value>::type* = nullptr) : v(i) {}
(未经测试!)