Недавно я написал класс журнала. При компиляции этого кода:
std::ofstream *stream = new std::ofstream;
stream->open( log_file_name.c_str() );
assert( stream->is_open() );
logger( stream, std::string("blurp") );
Я получаю сообщение об ошибке:
no match for call to '(name::space::logger)( std::ofstream*&, std::string )'
в отношении последней строки кода.
Файл заголовка, определяющий регистратор:
namespace name {
namespace space {
class logger {
private:
std::ofstream *stream;
std::string name;
public:
void log( std::string, std::string );
logger( std::ofstream *, std::string );
logger();
};
}
}
И я реализовал все функции/конструкторы, прототипированные там без ошибок.
Что может быть причиной этого? Спасибо за ваше время, Эрлинг.
Компилятор считает, что вы вызываете operator()
на объект, называемый logger
. Кажется, что вы хотите сделать, это создать экземпляр logger
:
logger log(stream, std::string("blurp") );
Здесь log
- это экземпляр класса name::space::logger
.
logger(stream, string("blurp"));
вызовет конструктор, создав безымянный временный. Если только я не вижу некой «самой неприятной проблемы».
GCC имеет этот странный способ сообщения типов аргументов функции.
Когда вы это сделаете:
logger( stream, std::string("blurp") );
компилятор видит вызов конструктора logger (name::space::logger
), первый аргумент которого является значением lvalue (в данном случае простой переменной) типа std::ostream*
, а второй является rvalue (временным построенный на месте) типа std::string
. Он сообщает об этом в качестве сигнатуры вызова (name::space::logger)(std::ostream*&, std::string)
- ссылка &
(значение lvalue) здесь просто указывает, что аргумент является lvalue. Это не влияет на возможность сопоставить его с типом параметра std::ostream*
.
Прежде всего, нет необходимости использовать указатель для ostream
. Поскольку это не Java, вы можете создавать объекты в стеке и без new
.
Тогда похоже, что ваш компилятор не видел, что у logger
есть конструктор с указателем потока и строкой. Из вызываемого вами вызова предполагается, что подпись должна быть чем-то вроде std::ofstream*&, std::string
, но предоставленный вами конструктор идеально соответствует этому предположению (см. Ответ Sebastian Redl для деталей).
Итак, что здесь может быть не так?
logger
классов не было определено)#include
найдет более старую версию, а не ту, в которую вы ввели конструктор. Лучшая возможность найти это введя некоторую явную ошибку в заголовке и снова скомпилируем. Если компилятор не жалуется на ошибку, он явно не включает заголовок, который вы редактируете.