Ошибка при попытке вывести endl: no match for ‘operator<<’ (operand types are ‘A’ and ‘<unresolved overloaded function type>’)

339
30 марта 2017, 22:04

Хочу написать класс обертку, который в зависимости от переменных будет или не будет выводить лог в stdout и/или файл log.txt.

#include <iostream>
#include <fstream>
using namespace std;
struct A {
  bool use_log = 1, use_filelog = 0;
  ofstream log_file;
  void open() {
    use_filelog = 1;
    log_file.open("log.txt");
  }
};
template <class T> A &operator<<(A &a, T x) {
  if (a.use_log) {
    std::cout << x;
  }
  if (a.use_filelog) {
    a.log_file << x;
  }
  return a;
}
int main() {
  A a;
  a << "Hello, World!" << endl; // <= ERROR
}

Получаю ошибку при попытке вывести endl. В чём проблема не пойму.

Может данный класс можно реализовать как-нибудь по другому?

Вот начало полотна вывода от gcc:

4.cpp: In function ‘int main()’:
4.cpp:26:24: error: no match for ‘operator<<’ (operand types are ‘A’ and ‘<unresolved overloaded function type>’)
   a << "Hello, World!" << endl;
                        ^
4.cpp:14:23: note: candidate: template<class T> A& operator<<(A&, T)
 template <class T> A &operator<<(A &a, T x) {
                       ^
4.cpp:14:23: note:   template argument deduction/substitution failed:
4.cpp:26:27: note:   couldn't deduce template parameter ‘T’
   a << "Hello, World!" << endl;
                           ^
In file included from /usr/include/c++/5/iostream:39:0,
                 from 4.cpp:1:
/usr/include/c++/5/ostream:628:5: note: candidate: template<class _CharT, class _Traits, class _Tp> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&)
     operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)

А вот от clang:

prog.cpp:26:27: error: reference to overloaded function could not be resolved; did you mean to call it?
  a << "Hello, World!" << endl;
                          ^~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/ostream:590:5: note: possible target for call
    endl(basic_ostream<_CharT, _Traits>& __os)
    ^
prog.cpp:14:23: note: candidate template ignored: couldn't infer template argument 'T'
template <class T> A &operator<<(A &a, T x) {
Answer 1

std::endl не имеет конкретного типа, ибо само по себе является шаблоном функции. Поэтому запись вида

a << endl;

является неоднозначной и вывести параметры шаблонов из нее невозможно. О чем вам и говорит компилятор. Чтобы устранить неоднозначность вам придется указывать параметры хотя бы одного из шаблонов явно.

Например, если вы явно укажете параметры шаблона std::endl

a << std::endl<char, std::char_traits<char>>;

то ваш тип T успешно дедуцируется и ваш оператор сработает, как задумано.

Но чтобы не извращаться подобным образом в реальности, можно поступить по аналогии со стандартными потоками и создать еще один оператор вывода, специально предназначенный для вывода std::endl

A &operator <<(A &a, 
               std::basic_ostream<char>& (*func)(std::basic_ostream<char>&))
{
  if (a.use_log) {
    std::cout << func;
  }
  if (a.use_filelog) {
    a.log_file << func;
  }      
  return a;
}

При этом реализацию этого оператора, после того как параметры шаблона std::endl уже зафиксировались, можно не выписывать явно, а делегировать в ваш шаблонный оператор (здесь нужно быть аккуратным, чтобы не устроить рекурсию)

A &operator <<(A &a, 
               std::basic_ostream<char>& (*func)(std::basic_ostream<char>&))
{
  return operator << <>(a, func);
}

А чтобы поддержать и остальные манипуляторы, придется реализовать и остальные операторы группы 10-12 по ссылке.

READ ALSO
C++ Builder ( вопрос по RichEdit or Memo)

C++ Builder ( вопрос по RichEdit or Memo)

Ребята, помогите! Вот например в RichEdit или у Memo есть "свойство", где хранятся строки(RichEdit1->Lines->Strings) - массив строк, которые я могу перебрать через...

359
Работа со строками(ввод строк)

Работа со строками(ввод строк)

Ребят, помогите реализовать, нужно, чтобы пользователь вводил слова в программу, используя стандартный поток ввода, а чтобы программа поняла,...

186
Отображение hex C-строки (cout &lt;&lt; hex &lt;&lt; int(char)) C++

Отображение hex C-строки (cout << hex << int(char)) C++

Есть функция, которая выводит hex C-строку, может есть более правильный способ?

191
Qt. Проблемы с QVector&lt;MyClass&gt;

Qt. Проблемы с QVector<MyClass>

Есть класс такого рода:

237