шаблоны ошибок копирования конструктора - PullRequest
0 голосов
/ 20 декабря 2011

Вот минимальный код, который показывает проблему:

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 ]

3 голосов
/ 20 декабря 2011

Насколько я понимаю, когда передается 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, поэтому единственным доступным конструктором является конструктор копирования.

0 голосов
/ 20 декабря 2011

Вы можете решить ее, определив функцию преобразования:

template<typename To, typename From> const To& convert(const From& x)
{
    return x;
}
0 голосов
/ 20 декабря 2011

Как и ожидалось, я удалил конструктор копирования по умолчанию.

Нет; в то время как вам нужно заменить конструктор копирования по умолчанию, его пропуск вызывает проблемы другого типа (и только если у вас есть код вызова, который в этом нуждается).

Ошибка, о которой вы сообщаете:

undefined reference to 'A convert<A, B>(B const&)

- ошибка компоновщика. Он говорит вам, что на самом деле у вас нет функции convert.

error: explicit specialization in non-namespace scope 'struct A'

Вы были правы в первый раз о том, как вернуть конструктор копирования по умолчанию. Однако это все равно не имеет отношения к ошибке компоновщика.

0 голосов
/ 20 декабря 2011

Что ж, «неопределенная ссылка» должна быть легко решена путем связывания в реализации функции!

ПРИМЕЧАНИЕ: при существующем состоянии возврат копии вызовет переполнение стека.

РЕДАКТИРОВАТЬ: IMO, ваш дизайн имеет недостатки, вы переместили логику построения за пределы A в convert;вместо этого вы должны предоставить конкретные конструкторы преобразования в A.Это либо тот, либо какой-то трюк boost::enable_if, чтобы отключить конструктор преобразования, если переданный тип получен из A (для этого можно использовать один из type_traits).Например, если вы можете создать A из int, укажите конкретный конструктор в самом A.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...