[英]Variadic Template Functions: No matching function for call, std::endl
In my code, I use variadic template functions for the logging purpose. 在我的代码中,我使用可变参数模板函数进行日志记录。 But when I use std::endl
as parameter, I get the following compiler error: 但是当我使用std::endl
作为参数时,我得到以下编译器错误:
Error: no matching function for call to 'LOG_ERROR(const char [14], int&, )' LOG_ERROR("Sum of x+y = ", z, std::endl); 错误:没有匹配函数来调用'LOG_ERROR(const char [14],int&,)'LOG_ERROR(“sum of x + y =”,z,std :: endl);
note: candidate: 'void LOG_ERROR()' inline void LOG_ERROR() { 注意:候选人:'void LOG_ERROR()'内联void LOG_ERROR(){
note: candidate expects 0 arguments, 3 provided 注意:候选人需要0个参数,3个提供
My Code: 我的代码:
#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);
}
The code works fine with "\\n"
but I would love to learn why it fails with std::endl
and how I can fix it 代码与"\\n"
一起工作正常,但我很想知道为什么它失败了std::endl
以及我如何解决它
Long story short - std::endl
is function template which template arguments can't be deduced while passing. std::endl
短 - std::endl
是函数模板,传递时不能推导出模板参数。 You can help Your compiler this way: 您可以这样帮助您的编译器:
LOG_ERROR("My foo = ", foo, std::endl<char, std::char_traits<char>>);
As much as I feel this is ugly piece of code it works perfectly. 尽管我觉得这是一段丑陋的代码,但它完美无缺。
Until someone comes with a better solution, you can use a trivial wrapper with an appropriate operator overload: 在有人提供更好的解决方案之前,您可以使用具有适当运算符重载的简单包装器:
struct EndlWrap {};
std::ostream& operator << (std::ostream& os, EndlWrap) {
return os << std::endl;
}
which should be usable like this: 应该像这样使用:
LOG_ERROR("My foo = ", foo, EndlWrap{});
This has an advantage when your logging destination might be a non-standard stream, ie, the template arguments of std::endl
can still be deduced when it's <<
'd into the stream. 这有一个好处,当你的日志目标可能是非标准流,即,模板参数std::endl
时,它仍然可以推断<<
倒是到流。
You can use defaulted template parameters and defaulted function arguments instead of a variadic template. 您可以使用默认模板参数和默认函数参数而不是可变参数模板。
The code is less clean and you will have to choose a limitation on the number of parameters, but it will do the job: 代码不太干净,您必须选择参数数量的限制,但它将完成工作:
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*/);
}
Depending on the compiler this code could produce ugly assembly. 根据编译器,此代码可能会产生丑陋的程序集。 One solution is to write an overload for each possible number of argument, or have a good knowldge of compiler specific function attributes (always_inline,etc...) 一种解决方案是为每个可能的参数编写一个重载,或者具有编译器特定函数属性的良好知识(always_inline等...)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.