Хочу написать класс обертку, который в зависимости от переменных будет или не будет выводить лог в 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) {
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 по ссылке.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Ребята, помогите! Вот например в RichEdit или у Memo есть "свойство", где хранятся строки(RichEdit1->Lines->Strings) - массив строк, которые я могу перебрать через...
Ребят, помогите реализовать, нужно, чтобы пользователь вводил слова в программу, используя стандартный поток ввода, а чтобы программа поняла,...
Есть функция, которая выводит hex C-строку, может есть более правильный способ?