C++ 未能专门化函数模板。重载运算符<&书信电报;
我正在尝试制作一个日志记录器,它记录到std::cout和一个文件。这是我的班级: .h文件:C++ 未能专门化函数模板。重载运算符<&书信电报;,c++,templates,C++,Templates,我正在尝试制作一个日志记录器,它记录到std::cout和一个文件。这是我的班级: .h文件: class ProblemsManager { (...) private: (...) class logger { private: std::ofstream fileStream; static const std::string LOG_PATH; public: logger();
class ProblemsManager {
(...)
private:
(...)
class logger {
private:
std::ofstream fileStream;
static const std::string LOG_PATH;
public:
logger();
~logger();
template<class T>
friend logger & operator<<(logger &log, const T & bytes) {
log.fileStream<<bytes;
std::cout<<bytes;
return log;
}
};
};
那么,如果我尝试这样做:
ProblemsManager::logger log;
log<<"test";
ProblemsManager::logger日志;
log可以是“f:\dropbox\workspace-visualstudio\peuler\peuler\problemsmanager.h(37)”中的友元函数:“作为操作符模板存在两个问题,第一个是两者仅在引用上不同,这将导致问题。您只需要一个(读取而不写入参数):
[*]这实际上可能是该规则的一个例外,因为它是一个私有类型,我只能假设记录器
的所有用法,因此操作符我将给出一个很长的尝试
log<<"test";
logI已经纠正了这一点并编辑了我的答案。有意思的是,模板函数的定义和声明是分开的;我认为这是不可能的,因为需要使用模板定义的每个文件都不能仅从声明生成它们(因为定义本身位于完全不同的cpp文件中)。我很惊讶它甚至编译了o.OIs这个记录器
类型私有于封闭类型ProblemsManager
?@Aggieboy:它不编译(这就是他问的原因),但你关心的是链接器错误。@DavidRodríguez dribeas Aha我明白了!我不明白为什么这不是编译器错误,但事后可能是链接器错误,删除其中一个重载并不能解决问题。对不起,什么是“文字字符串”?我认为这似乎解决了这个问题。但是现在我得到了1>f:\dropbox\workspace-visualstudio\peuler\peuler\problemsmanager.cpp(47):错误C3767:“我已经编辑了答案,显示了我的代码在moment@Trollkemada对于最新的代码,唯一的问题是logger
是私有的。把它公之于众对我来说很好。简单地说一下“例外”部分,这仍然是个坏主意。类头文件定义接口细节;公共函数由用户使用,私有函数和公共函数都在cpp文件中定义(不一定只有一个)。实现私有函数的Cpp文件将使用头文件中的其他私有函数作为接口。模板函数不能以这种方式使用,因为只有定义它们的cpp文件才能实际使用它们。@jrok:关于已删除(因为它不完整)答案的注释,仅在值/引用上重载没有问题,但当调用为左值时,重载将导致歧义,这不是你想要的。我已经编辑了我的问题。(现在,正如您所建议的,我只是在const reference上使用了一个重载)您的记录器仍然是私有的。我很惊讶,当您定义日志变量时,编译器并没有抱怨它。
template<class T>
friend logger & operator<<(logger& log, const T & bytes);
// ^^^^^
class ProblemsManager {
private:
class logger {
template<class T>
friend logger & operator<<(logger& log, T & bytes) {
// implementation goes here
}
};
};
log<<"test";