以下是显示问题的最小代码:
template<typename To, typename From> To convert(const From& x);
struct A
{
int value;
template<typename T> A(const T& x) { value = convert<A>(x).value; }
};
struct B : public A { };
int main()
{
B b;
A a = b;
}
它给了我:undefined reference to 'A convert<A, B>(B const&)'
正如所料,我删除了默认的复制构造函数。但是,如果我将此行添加到A
:
A(const A& x) { value = x.value; }
我得到了同样的错误。如果我尝试这样做:(添加模板专业化)
template<> A(const A& x) { value = x.value; }
我得到:error: explicit specialization in non-namespace scope 'struct A'
。
如何解决?
我的编译器是MinGW(GCC)4.6.1
编辑:
convert
函数会将许多类型转换为A
并再次返回。问题在于,由于继承,将转换函数从B
编写到A
是没有意义的。如果我从convert
删除了调用A
的行,那么它就可以了。我们的想法是在convert
继承的所有时间都调用A
,对于这些,默认构造函数应该足够了。
答案 0 :(得分:3)
据我了解,当b
传递时,由于b
不是A
的对象,因此不调用复制构造函数,而是调用模板构造函数。
但是,如果传递了派生类的对象,则需要调用A
的复制构造函数。
为此,有一个解决方案使用<type_traits>
(c ++ 0x):
#include <type_traits>
template<typename To, typename From> To convert(const From& x);
struct A
{
int value;
template<typename T> A(const T& x,
const typename std::enable_if<!std::is_base_of<A,T>::value, bool>::type = false)
{ value = convert<A>(x).value; }
A(){}
};
struct B : public A { };
int main()
{
B b;
A a = b;
}
禁用模板为什么传递从A
派生的类的对象,因此唯一可用的构造函数是复制构造函数。
答案 1 :(得分:0)
嗯,应该通过链接函数的实现来轻松解决“未定义的引用”!
注意:事实上,返回副本将触发堆栈溢出。
编辑:IMO,您的设计存在缺陷,您已将A
之外的构造逻辑移至convert
;而不是这个,你应该在A
中提供特定的转换构造函数。如果传入的类型是从boost::enable_if
派生的,那么要么禁用转换构造函数,要么使用A
技巧(您可以使用其中一个type_traits
)。例如,如果您可以从A
构建int
,请在A
本身中提供具体的构造函数。
答案 2 :(得分:0)
您可以通过定义转换函数来解决它:
template<typename To, typename From> const To& convert(const From& x)
{
return x;
}
答案 3 :(得分:0)
正如所料,我删除了默认的复制构造函数。
没有;虽然你确实需要替换默认的复制构造函数,但是它的遗漏会导致一种不同的问题(并且只有当你有那种需要它的调用代码时)。
您报告的错误:
undefined reference to 'A convert<A, B>(B const&)
是链接器错误。它告诉你,你实际上并没有convert
函数。
error: explicit specialization in non-namespace scope 'struct A'
关于如何放回默认的复制构造函数,你是第一次。但是,这仍然与链接器错误无关。