2016-05-02 2 views
8

Я пытаюсь получить функцию друга внутри шаблона, чтобы компилировать, но сообщение об ошибке и предупреждение я не понимаю. Я сделал демонстрацию проблемы. Ошибка я получаю:Templated Class Friend Operator Member Function

prog.cpp:8:57: error: non-class, non-variable partial specialization C operator+(const B& lhs, const C& rhs);

prog.cpp:15:59: warning: friend declaration 'C operator+(const B&, const C&)' declares a non-template function [-Wnon-template-friend] friend C operator+(const B& lhs, const C& rhs);

prog.cpp:15:59: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)

#include <iostream> 
using namespace std; 

template<typename A, typename B> 
class C; 

template<typename A, typename B> 
C<A, B> operator+<A, B>(const B& lhs, const C<A, B>& rhs); 

template<typename A, typename B> 
struct C 
{ 
    A val_; 
    C operator+(const C& other) const; 
    friend C<A, B> operator+(const B& lhs, const C<A, B>& rhs); 
}; 

template<typename A, typename B> 
C<A, B> C<A, B>::operator+(const C<A, B>& other) const 
{ 
    C<A, B> c; 
    c.val_ = this->val_ + other.val_; 
    return c; 
} 

template<typename A, typename B> 
C<A, B> operator+(const B& lhs, const C<A, B>& rhs) 
{ 
    C<A, B> c; 
    c.val_ = lhs + rhs.val_; 
    return c; 
} 

int main() 
{ 
    C<string, char> c0,c1; 
    c0.val_ = " C0 "; 
    c1.val_ = " C1 "; 
    cout << "Stuct:" << (c0 + c1).val_ << '\n'; 
    cout << "Friend:" << ('~' + c1).val_ << endl; 
    return 0; 
} 
+0

Вам не нужно первое объявление 'оператора +', что неправильно. – Holt

+0

Это пример проблемы. Мне нужно три формы в моем действительном коде: оператор C + (const C & other), оператор C + (const B & other) и оператор C (const B & lss, const C & rhs). Нотабене а не фактический компиляционный код, просто общие формы необходимости. – JadziaMD

ответ

3

Эта декларация:

template<typename A, typename B> 
C<A, B> operator+<A, B>(const B& lhs, const C<A, B>& rhs); 

... неправильно из-за <A,B> между operator+ и (, я действительно не знаю, что вы хотел сделать здесь. Вы бы использовали эту форму, если бы вы были specialize a templated operator+, но вас нет здесь, вы перегрузка.

Это заявление должно быть:

template<typename A, typename B> 
C<A, B> operator+ (const B& lhs, const C<A, B>& rhs); 

Затем вы должны явно указать в friend декларации, которую вы хотите специализированную версию по Writting:

friend C<A,B> operator+<>(const B& lhs, const C<A,B>& rhs); 

Вы должны поместить это, прежде чем ваш operator+, otherwize компилятор подумает, что это специализация не templated функции.

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


весь Ваш код должен выглядеть следующим образом:

// Declaration of struct C with delayed definition 
template <typename A, typename B> 
struct C; 

// Initial declaration of templated operator+ 
template <typename A, typename B> 
C<A, B> operator+ (const B&, const C<A, B>&); 

// Definition of C 
template <typename A, typename B> 
struct C { 

    friend C operator+<> (const B&, const C&); 

    // This must be AFTER the templated operator+ 
    C operator+ (const C&) const; 
}; 

template<typename A, typename B> 
C<A, B> C<A, B>::operator+(const C<A, B>& other) const { 

} 

template<typename A, typename B> 
C<A, B> operator+(const B& lhs, const C<A, B>& rhs) { 

} 
+0

У меня есть такая причина. :) Я применил предложенные изменения кода в примере, но теперь я получаю сообщение об ошибке: prog.cpp: 19: 24: ошибка: объявление оператора «+» как недействительное друг C operator + <> (const B & ls, const C & rhs); ^ prog.cpp: 19: 24: error: expected ';' в конце объявления участника prog.cpp: 19: 26: ошибка: ожидаемый неквалифицированный идентификатор до «<» токена друг C оператор + <> (const B & lhs, const C & rhs) – JadziaMD

+1

@JadziaMD Вам нужно поставить оператор 'C + <> (const B & lhs, const C & rhs) '** перед ** любым другим немодулированным' operator + 'внутри' C'. Я уточню свой ответ. – Holt

5

Самый простой встраивать код внутри класса:

template <typename A, typename B> 
struct C 
{ 
    A val_; 
    C operator+(const C& other) const 
    { 
     C c; 
     c.val_ = this->val_ + other.val_; 
     return c; 
    } 

    friend C operator+ (const B& lhs, const C& rhs) 
    { 
     C c; 
     c.val_ = lhs + rhs.val_; 
     return c; 
    } 
}; 

Demo

код не встраиваются в класс, который требует большого внимания в качестве форвардного декларирования порядка объявления, странно синтаксис <>:

template <typename A, typename B> struct C; 

template <typename A, typename B> 
C<A, B> operator+ (const B& lhs, const C<A, B>& rhs); 

template <typename A, typename B> 
struct C 
{ 
    A val_; 

    friend C<A, B> operator+<> (const B& lhs, const C<A, B>& rhs); 

    C operator+(const C& other) const; 
}; 


template <typename A, typename B> 
C<A, B> operator+ (const B& lhs, const C<A, B>& rhs) 
{ 
    C<A, B> c; 
    c.val_ = lhs + rhs.val_; 
    return c; 
} 

template <typename A, typename B> 
C<A, B> C::operator+(const C<A, B>& other) const 
{ 
    C<A, B> c; 
    c.val_ = this->val_ + other.val_; 
    return c; 
} 

Demo