以下版本不能用g ++ 4.4.7编译,在命令行上传递了--std == c ++ 0x:
#include <algorithm>
#include <iostream>
template <typename T>
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 <typename V>
explicit A(const V& i): v(i) {}
#endif
};
class B: public A<int>
{
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<int>(i) {
std::cout << "B copy constructor\n"; }
B(B&& i): A<int>(std::move(i)) {
std::cout << "B move constructor\n"; }
#else
B(const B& i): A<int>(static_cast<const A<int> &>(i)) {
std::cout << "B copy constructor\n"; }
B(B&& i): A<int>(std::move(static_cast<A<int> &&>(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<T>::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) {}
问题:
答案 0 :(得分:5)
似乎复制和移动构造函数调用显式A模板而不是A的明显复制/移动构造函数:
调用A(A const&)
构造函数没有什么明显之处:您使用A
类型的参数调用B const&
构造函数,并且最佳匹配就是模板(是完全匹配),而不是A(A const&)
,不是完全匹配(它需要隐式向上)。
所以这种行为完全符合预期。如果您不想这样做,请更改模板,以便在使用A
的子类(通过SFINAE)调用时禁用它:
template <typename V>
explicit A(const V& i,
typename std::enable_if<! std::is_base_of<A, V>::value>::type* = nullptr)
: v(i) {}
(未经测试!)