Вопрос по c++ – Оператор перегрузки <<: не может связать lvalue с ‘std :: basic_ostream &&’

41

Error: User Rate Limit Exceededoperator<<Error: User Rate Limit Exceededoperator<<Error: User Rate Limit Exceeded

#include <memory>
#include <iostream>

template<typename T>
struct classA {
  struct classB
  {
    template<typename U>
    friend inline std::ostream& operator<< (std::ostream &out,
                                            const typename classA<U>::classB &b);
  };

  classB root;

  template<typename U>
  friend std::ostream& operator<< (std::ostream &out,
                                   const classA<U> &tree);
};

template<typename T>
inline std::ostream& operator<< (std::ostream &out,
                                 const classA<T> &tree)
{
  out << tree.root;
  return out;
}

template<typename T>
inline std::ostream& operator<< (std::ostream &out,
                                 const typename classA<T>::classB &b)
{
  return out;
}

int main()
{
  classA<int> a;
  std::cout << a;
}

When compiling without support for C++11, the definition of operator<< for the inner class seems not to be found by the compiler:

so.hpp:24:7: error: no match for ‘operator<<’ in ‘out << tree.classA<int>::root’
so.hpp:24:7: note: candidates are: ...

With GCC 4.6 and 4.7 when compiling with std=c++0x:

so.hpp:21:3: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
In file included from /usr/include/c++/4.7/iostream:40:0,
                 from so.hpp:2:
/usr/include/c++/4.7/ostream:600:5: error:   initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = classA<int>::classB]’

Error: User Rate Limit Exceeded

Ваш Ответ

3   ответа
23

Error: User Rate Limit ExceededreasonError: User Rate Limit ExceededTError: User Rate Limit Exceededoperator<<Error: User Rate Limit ExceededdefineError: User Rate Limit Exceeded

template<typename T>
struct classA {
  struct classB
  {
    friend inline std::ostream& operator<< (std::ostream &out,
                                            const classB &b) {
       // definition goes here
    }
  };

  classB root;

  friend std::ostream& operator<< (std::ostream &out,
                                   const classA<U> &tree) {
       // definition goes here
  }
};

Error: User Rate Limit Exceededoperator<<Error: User Rate Limit ExceededtighterError: User Rate Limit ExceededoneError: User Rate Limit Exceededoperator<<Error: User Rate Limit ExceededClassA<T>Error: User Rate Limit ExceededClassA<T>::ClassB.


How access can be gained with your approach

namespace {
   struct intruder {
       ClassA & ref;
       intruder( ClassA& r ) : ref(r) {}
   };
   template <>
   std::ostream& operator<< <intruder>( std::ostream& _, ClassA<intruder> const& i ) {
       std::cout << i.ref.private_member << std::endl;
       return _;
   }
}

Alternative

Error: User Rate Limit ExceededintruderError: User Rate Limit Exceededoperator<<Error: User Rate Limit ExceededClassA<intruder>Error: User Rate Limit Exceeded

@TBBle: Хорошо, что кто-то нашел название для него, но эта идиома использовалась долгое время без имени, и это просто прекрасно :)
ЭтоMaking New Friends идиома, так что на самом деле не обходной путь.
Я не хотел подразумевать, что он перестал быть обходным путем, как только его назвали. Это название для идиомы, по крайней мере,10 years old,changes that made it necessary хотя на 10 лет старше этого, насколько я могу судить. Хотя в то время примеры этого варианта использования, казалось, все шли с «предварительным объявлением».
Спасибо за предоставленное решение. Antoine
Я вижу это какbetter design а неworkaround, У него есть и обратная сторона (вы не можете взять адрес функции друга, объявленной внутри класса шаблона), но для всех остальных учетных записей лучше использовать бесплатные операторы функций ...
28

Error: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit Exceeded

template<typename T>
inline std::ostream& operator<< (std::ostream &out,
                                 const typename classA<T>::classB &b)
{
  return out;
}

Error: User Rate Limit ExceededTError: User Rate Limit ExceededclassBError: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&)

Error: User Rate Limit ExceededcanError: User Rate Limit Exceeded_TpError: User Rate Limit ExceededclassA<T>::classBError: User Rate Limit Exceeded

Комментарий о близком совпадении дал понять, почему у меня возникла подобная проблема.
2

Error: User Rate Limit Exceeded

template<typename T>
inline std::ostream& operator<< (std::ostream &out,
                             const classA<T> &tree)
{
   //out << tree.root;
   ::operator<<( out, tree.root);
   return out;
}

Error: User Rate Limit Exceeded

test.cpp:34:3: error: no matching function for call to ‘operator<<(std::ostream&, const classA<int>::classB&)’
test.cpp:34:3: note: candidates are:
test.cpp:23:22: note: template<class T> std::ostream& operator<<(std::ostream&, const     typename classA<T>::classB&)
test.cpp:30:22: note: template<class T> std::ostream& operator<<(std::ostream&, const classA<T>&)

Error: User Rate Limit Exceeded

Вы всегда можете явно позвонить::operator<< <T> (out, tree.root) вместо этого, но я думаю, что именованные функции-члены теперь выглядят более привлекательно.

Похожие вопросы