Явная реализация оператора >> перегрузка - PullRequest
1 голос
/ 08 марта 2012

У меня есть класс Vector<T>, и я использую библиотеку, которая предоставляет класс YAML::Node.Я хотел бы перегрузить operator>> для этих двух типов.

Я добавил следующее объявление к объявлению Vector:

friend void operator>>(YAML::Node const & node, Vector<T> & v);

Я также добавил следующую реализациюфункция:

template<typename T>
void operator>>(YAML::Node const & node, Vector<T> & v) {
    node[0] >> v.x;
    node[1] >> v.y;
    node[2] >> v.z;
}

Наконец, я добавил следующую (попытку) явной реализации шаблона для T = num_t:

template
void operator>>(YAML::Node const & node, Vector<num_t> & v);

Однако это приводит к следующей ошибке компоновщика:

Error   9   error LNK2019: unresolved external symbol "void __cdecl operator>>(class YAML::Node const &,class Vector<double> &)" (??5@YAXAEBVNode@YAML@@AEAV?$Vector@N@@@Z) referenced in function "public: static class Scene __cdecl Scene::fromFile(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?fromFile@Scene@@SA?AV1@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)

(num_t - это typedef для double)

Однако, если я добавлю следующую (не шаблонную) реализацию функции, все прекрасно скомпилируется:1024 *

void operator>>(YAML::Node const & node, Vector<num_t> & v) {
    node[0] >> v.x;
    node[1] >> v.y;
    node[2] >> v.z;
}

Почему шаблонная версия функции не работает?

Редактировать: Забыл упомянуть;компилятор Visual Studio 11 Beta

Ответы [ 3 ]

3 голосов
/ 08 марта 2012

Объявление функции как friend означает не объявление шаблона функции; вместо этого каждая специализация шаблона класса объявляет не шаблонную функцию с типами параметров, перегруженными в соответствии с аргументами шаблона. Они будут выбраны вместо шаблона, который вы определяете; но они не определены, отсюда и ошибка.

Чтобы исправить это, вы можете либо объявить шаблон функции перед шаблоном класса (в этом случае объявление друга сделает этого другом, чем объявить новую функцию), либо определить встроенную функцию друга внутри шаблона класса , так что каждая специализация шаблона класса определяет функцию, а также объявляет ее.

2 голосов
/ 08 марта 2012

Ну, проблема в том, что объявленная вами friend - это не шаблонная функция, которая не имеет никакого отношения к вашему оператору сдвига. Фактически, ваш шаблон использует любые закрытые члены, на которые должен пожаловаться компилятор. Вот пример, как это должно выглядеть:

template <typename T>
class foo
{
public:
    template <typename S>
    friend void f(foo<S>);

private:
    T value;
};

template <typename T>
void f(foo<T> v)
{
    v.value;
}
template void f(foo<int>);

int main()
{
    foo<int> v;
    f(v);
}

Если вы замените объявление друга на

friend void f(foo<T>);

Этот код также не будет ссылаться и фактически выдаст ошибку времени компиляции, указывающую, что функция f() не является другом.

0 голосов
/ 08 марта 2012

Это странно.Я не вижу ничего плохого, и даже документация MSDN (это Visual C ++, верно?) Подтверждает, что создание шаблона должно выводить аргументы шаблона.Аргументы в экземпляре совпадают.Может быть, он не работает для перегруженных операторов?

Не мешало бы попытаться добавить к нему явные аргументы шаблона.

Кроме того, возможно, его смущает typedef?Никогда не знаешь!Попробуйте заменить double.

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