2009-06-07 3 views
5

Недавно я пытался оценить возможности перегрузки/шаблона моего оператора и в качестве небольшого теста создал класс контейнера ниже. Хотя этот код хорошо компилируется и работает корректно в MSVC 2008 (отображает 11), как MinGW/GCC, так и Comeau подавляют перегрузку operator+. Поскольку я доверяю им больше, чем MSVC, я пытаюсь понять, что я делаю неправильно.Перегрузка двоичных операторов на шаблонный класс

Вот код:

#include <iostream> 

using namespace std; 

template <typename T> 
class Container 
{ 
     friend Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs); 
    public: void setobj(T ob); 
    T getobj(); 
     private: T obj; 
}; 

template <typename T> 
void Container<T>::setobj(T ob) 
{ 
    obj = ob; 
} 

template <typename T> 
T Container<T>::getobj() 
{ 
    return obj; 
} 

template <typename T> 
Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs) 
{ 
     Container<T> temp; 
     temp.obj = lhs.obj + rhs.obj; 
     return temp; 
} 

int main() 
{  
    Container<int> a, b; 

a.setobj(5); 
    b.setobj(6); 

Container<int> c = a + b; 

cout << c.getobj() << endl; 

    return 0; 
} 

Это ошибка Комео дает:

Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2 
Copyright 1988-2008 Comeau Computing. All rights reserved. 
MODE:strict errors C++ C++0x_extensions 

"ComeauTest.c", line 27: error: an explicit template argument list is not allowed 
      on this declaration 
    Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs) 
      ^

1 error detected in the compilation of "ComeauTest.c". 

Я с трудом пытается получить Комю/MingGW, чтобы играть в мяч, так что там Я обращаюсь к вам, ребята. Прошло много времени с тех пор, как мой мозг растопил это под вес синтаксиса C++, поэтому я немного смущен;).

EDIT: Устранена ошибка (несущественная) lvalue, указанная в исходной дампе Комо.

ответ

5

Я нашел решение благодаря to this forum posting. По сути, вам нужно иметь прототип функции, прежде чем вы сможете использовать «friend» на нем в классе, однако вам также нужен класс для объявления, чтобы правильно определить прототип функции. Следовательно, решение должно состоять из двух прототипов (функции и класса) в верхней части. Следующий код компилирует в рамках всех трех составителей:

#include <iostream> 

using namespace std; 

//added lines below 
template<typename T> class Container; 
template<typename T> Container<T> operator+ (Container<T>& lhs, Container<T>& rhs); 

template <typename T> 
class Container 
{ 
     friend Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs); 
     public: void setobj(T ob); 
       T getobj(); 
     private: T obj; 
}; 

template <typename T> 
void Container<T>::setobj(T ob) 
{ 
     obj = ob; 
} 

template <typename T> 
T Container<T>::getobj() 
{ 
     return obj; 
} 

template <typename T> 
Container<T> operator+ (Container<T>& lhs, Container<T>& rhs) 
{ 
     Container<T> temp; 
     temp.obj = lhs.obj + rhs.obj; 
     return temp; 
} 

int main() 
{  
    Container<int> a, b; 

    a.setobj(5); 
    b.setobj(6); 

    Container<int> c = a + b; 

    cout << c.getobj() << endl; 

    return 0; 
} 
2
template <typename T> 
Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs) 

Здесь «<>» после того, как operator+ должны быть удалены, так как вы просто объявить новый шаблон, не специализирующийся на общей. Также по крайней мере g++ хочет увидеть объявление шаблона перед объявлением друга, поэтому его необходимо перенести перед объявлением Container. Таким образом, следующий порядок объявлений работ:

// forward declaration of Container<T> 
template <typename T> 
class Container; 

template <typename T> 
Container<T> operator+(Container<T>& lhs, Container<T>& rhs) 
{ ... } 

template <typename T> 
class Container 
{ 
     friend Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs); 
     ... 
}; 
0

«оператор +» не является функцией-членом, и это не шаблонный. Это просто оператор +, который принимает шаблонные параметры ».

template <typename T> 
Container<T> operator+ (Container<T>& lhs, Container<T>& rhs) 
+1

Я думаю, что оператор + является шаблонизированной функцией, не так ли? Контейнер и контейнер будут двух разных типов, поэтому компилятору необходимо будет сгенерировать две разные функции оператора +, чтобы справиться с ними. Разве это не означает, что оператор + является шаблонизированной функцией? –

+0

It * есть * функция шаблон. Но вы правильно указали «<>» из определения шаблона. («<>» используется только при указании шаблона функции * для вызова *, и даже тогда это необходимо только тогда, когда существует функция без шаблона с тем же именем.) –

1

Я дал этот снимок под GCC и получил его для компиляции и запуска с несколькими изменениями. Было два изменения, которые я должен был сделать, чтобы GCC был счастлив.

Одним из них является объявление функции шаблона друга. Это собственное объявление шаблона отдельно от класса, поэтому я использовал U вместо класса Container T. Я также избавился от <> после оператора +. Я не думаю, что вам это понадобится, если вы не написали специализацию шаблона.

 template<typename U> 
     friend Container<U> operator+ (Container<U>& lhs, Container<U>& rhs); 

Два, линия

не полететь с GCC, потому что вы просите, чтобы сохранить ссылку на временный (результат сложения). Я удалил амперсанд, чтобы было место для хранения результата.

Я видел ваше сообщение только сейчас, это также работает из-за передовых объявлений. Думаю, я все равно отправлю это как альтернативу, которая их не требует. Конечно, я тестировал только в GCC ...

+0

Я нашел это в другом размещении в Интернете, и это будет мой личное предпочтение двух (более кратким). – GRB

+0

Этот будет предоставлять доступ ко всем специализированным специализациям (так что оператор + может получить доступ к частным лицам Контейнера ). Код искателя хочет предоставить доступ только к оператору + (только оператор + может получить доступ к частным лицам контейнера ) –

+0

@litb: Я тоже видел этот вопрос, но у меня возникли проблемы с настройкой такого сценария. Не могли бы вы предоставить примерный фрагмент кода, где int overload обращается к закрытым членам float? – GRB

1

Вам было бы лучше определить функцию непосредственно в классе. Кроме того, вы должны передать параметры как const ссылок.

template <typename T> 
class Container 
{ 
public: 
    friend Container operator+ (Container const & lhs, Container const & rhs) 
    { 
     // ... 
    } 
}; 
Смежные вопросы