在我的代码中,我使用 可变模板函数 进行记录。但是当我使用std::endl
作为参数时,出现以下编译器错误:
错误:没有匹配的函数可以调用'LOG_ERROR(const char [14], int&,)'LOG_ERROR(“ 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
上失败,以及如何解决该问题
答案 0 :(得分:8)
长话短说-std::endl
是函数模板,传递时无法推导出模板参数。您可以通过以下方式帮助您的编译器:
LOG_ERROR("My foo = ", foo, std::endl<char, std::char_traits<char>>);
就我所知,这是丑陋的代码,可以完美地工作。
答案 1 :(得分:7)
在有人提供更好的解决方案之前,您可以使用带有适当运算符重载的琐碎包装器:
struct EndlWrap {};
std::ostream& operator << (std::ostream& os, EndlWrap) {
return os << std::endl;
}
应该可以这样使用:
LOG_ERROR("My foo = ", foo, EndlWrap{});
当您的日志记录目标可能是非标准流时,这是有优势的,即,std::endl
的模板参数在被<<
插入流中时仍然可以推导出来。
答案 2 :(得分:1)
std::endl
不是字符类型或任何其他类型。它是输出流操纵器。它的返回类型是输出流。
因此,没有类型转换,您将无法通过它。请查看here
答案 3 :(得分:1)
您可以使用默认模板参数和默认函数参数来代替可变参数模板。
代码不太干净,您将不得不选择参数数量的限制,但是它将起作用:
template<class...>
inline void LOG_ERROR_();
template<>
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_<Rest...>(std::forward<Rest>(rest)...);
//could be cleaner with if constexpr
}
using manip_t = std::basic_ostream<char>&(*)(std::basic_ostream<char>&);
std::basic_ostream<char>& no_manip(std::basic_ostream<char>& o){
return o;
}
template<typename A=manip_t
,typename B=manip_t, typename C= manip_t
,typename D=manip_t // to be continued
>
inline void LOG_ERROR(A&& a=no_manip, B&& b=no_manip,C&& c=no_manip
,D&& d=no_manip /*to be continued*/){
LOG_ERROR_<A,B,C,D/*to be continued*/>(
std::forward<A>(a),std::forward<B>(b),std::forward<C>(c),
std::forward<D>(d)/*to be continued*/);
}
取决于编译器,此代码可能会产生难看的汇编。一种解决方案是为每个可能的参数数量写一个重载,或者对编译器特定的函数属性(always_inline等)有足够的了解