Перегрузка оператора внутреннего класса в шаблоне C ++ - PullRequest
0 голосов
/ 17 мая 2018

Я пытаюсь реализовать перегрузку для operator!=, которая сравнивает два объекта разных типов (InnerA и InnerB).Оба типа определены как вложенные классы в шаблонном классе (Outer).Перегрузка должна быть другом обоих классов, так как она обращается к приватным полям каждого из них.

template<typename Type> class Outer
{
public:
    class InnerA;
    class InnerB;
};


template<typename Type> bool operator!=(const typename Outer<Type>::InnerA& lhs, const typename Outer<Type>::InnerB& rhs);


template<typename Type> class Outer<Type>::InnerA
{
    const int val = 0;
    friend bool operator!=<>(const InnerA& lhs, const typename Outer<Type>::InnerB& rhs);
};


template<typename Type> class Outer<Type>::InnerB
{
    const int val = 1;
    friend bool operator!=<>(const typename Outer<Type>::InnerA& lhs, const InnerB& rhs);
};


template<typename Type> bool operator!=(const typename Outer<Type>::InnerA& lhs, const typename Outer<Type>::InnerB& rhs)
{
    return lhs.val != rhs.val;
}


int main()
{
    bool b = Outer<int>::InnerA() != Outer<int>::InnerB();
}

Приведенный выше код не может быть скомпилирован, выдавая:

 In instantiation of 'class Outer<int>::InnerA':
34:33: required from here 
15:17: error: template-id 'operator!=<>' for 'bool operator!=(const Outer<int>::InnerA&, const Outer<int>::InnerB&)' does not match any template declaration 
 In instantiation of 'class Outer<int>::InnerB': 
34:57: required from here 
22:17: error: template-id 'operator!=<>' for 'bool operator!=(const Outer<int>::InnerA&, const Outer<int>::InnerB&)' does not match any template declaration 
 In function 'int main()': 
34:35: error: no match for 'operator!=' (operand types are 'Outer<int>::InnerA' and 'Outer<int>::InnerB') 
34:35: note: candidate is: 
26:30: note: template<class Type> bool operator!=(const typename Outer<Type>::InnerA&, const typename Outer<Type>::InnerB&) 
26:30: note: template argument deduction/substitution failed: 
34:57: note: couldn't deduce template parameter 'Type'

Хотя может быть лучшеспособы достижения аналогичного результата, мне любопытно, что именно не так с моим кодом.Спасибо!

Ответы [ 3 ]

0 голосов
/ 17 мая 2018

Я нашел следующий обходной путь, рефакторинг перегрузки как метод одного из вложенных классов:

template<typename Type> class Outer
{
public:
    class InnerA;
    class InnerB;
};


template<typename Type> class Outer<Type>::InnerA
{
    const int val = 0;
public:
    bool operator!=(const typename Outer<Type>::InnerB& other);
};


template<typename Type> class Outer<Type>::InnerB
{
    const int val = 1;
    friend bool Outer<Type>::InnerA::operator!=(const InnerB& other);
};


template<typename Type> bool Outer<Type>::InnerA::operator!=(const typename Outer<Type>::InnerB& other)
{
    return val != other.val;
}


int main()
{
    bool b = Outer<void>::InnerA() != Outer<void>::InnerB();
}

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

0 голосов
/ 21 мая 2018

Проблема с кодом в вопросе закончилась тем, что шаблонное удержание не предпринималось для имен типов, вложенных в зависимый тип (например, Outer<Type>::Inner).

Этот вопрос по сути является дубликатом Вложенного шаблона и определения параметров . Подробное объяснение, почему это проблема, можно найти здесь .

0 голосов
/ 17 мая 2018
template<typename Type> class Outer<Type>::InnerA
{
   friend bool operator!=(const InnerA& lhs, const typename Outer<Type>::InnerB& rhs) { return true; }
};
template<typename Type> class Outer<Type>::InnerB
{
  friend bool operator!=(const typename Outer<Type>::InnerA& lhs, const InnerB& rhs) { return true; }
};

это не шаблонные друзья. Они также конфликтуют. Так что реализуй один из них, пропусти другой.

Они будут найдены через ADL.

...