在我的代码中,我使用 variadic template functions 进行日志记录 . 但是当我使用 std::endl
作为参数时,我得到以下编译器错误:
错误:没有匹配函数来调用'LOG_ERROR(const char [14],int&,)'LOG_ERROR(“sum of x y =”,z,std :: endl);注意:候选:'void LOG_ERROR()'内联void LOG_ERROR(){注意:候选者需要0个参数,3个提供
我的代码:
#include <iostream>
inline void LOG_ERROR() {
std::cout << std::endl;
}
template<typename First, typename ...Rest>
void LOG_ERROR(First && first, Rest && ...rest){
std::cout << std::forward<First>(first);
LOG_ERROR(std::forward<Rest>(rest)...);
}
int main() {
int foo=40;
LOG_ERROR("My foo = ", foo, std::endl);
}
代码与 "\n"
工作正常,但我很想知道为什么它失败 std::endl
以及如何解决它
4 回答
std::endl
不是字符类型或任何其他类型 . 它是输出流操纵器 . 它的返回类型是输出流 .所以,如果没有类型转换,你就无法通过它 . 请看here
长话短说 -
std::endl
是函数模板,传递时不能推导出模板参数 . 您可以这样帮助您的编译器:尽管我觉得这是一段丑陋的代码,但它完美无缺 .
在有人提供更好的解决方案之前,您可以使用具有适当运算符重载的普通包装器:
这应该是这样的:
当您的日志记录目标可能是非标准流时,这有一个优势,即
std::endl
的模板参数在进入流时仍然可以推导出来 .您可以使用默认模板参数和默认函数参数而不是可变参数模板 .
代码不太干净,您必须选择参数数量的限制,但它将完成工作:
根据编译器,此代码可能会产生丑陋的程序集 . 一种解决方案是为每个可能的参数编写一个重载,或者具有编译器特定函数属性的良好知识(always_inline等...)