模板复制构造函数错误

时间:2011-12-20 13:23:09

标签: c++ templates c++11

以下是显示问题的最小代码:

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,对于这些,默认构造函数应该足够了。

4 个答案:

答案 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'

关于如何放回默认的复制构造函数,你是第一次。但是,这仍然与链接器错误无关。