可变参数模板函数:没有匹配的函数,用于调用std :: endl

ene*_*ski 7 c++ variadic-templates c++11

在我的代码中,我使用可变参数模板函数进行日志记录.但是当我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);
}
Run Code Online (Sandbox Code Playgroud)

代码工作得很好,"\n"但我很想知道它为什么失败std::endl以及如何解决它

bar*_*top 8

长话短说 - std::endl是函数模板,模板参数在传递时无法推断.您可以这样帮助您的编译器:

LOG_ERROR("My foo = ", foo, std::endl<char, std::char_traits<char>>);
Run Code Online (Sandbox Code Playgroud)

尽管我觉得这是一段丑陋的代码,但它完美无缺.


lub*_*bgr 7

在有人提供更好的解决方案之前,您可以使用具有适当运算符重载的简单包装器:

struct EndlWrap {};

std::ostream& operator << (std::ostream& os, EndlWrap) {
   return os << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

应该像这样使用:

LOG_ERROR("My foo = ", foo, EndlWrap{});
Run Code Online (Sandbox Code Playgroud)

当您的日志记录目标可能是非标准流时,这有一个优势,即,std::endl当它<<进入流时,仍然可以推导出模板参数.

  • 可能:`auto EndlWrap = [](auto && os) - > decltype(auto){return os << std :: endl; }`.它也适用于`std :: wcout`.(或模板化你的功能). (4认同)

小智 1

std::endl不是字符类型或任何其他类型。它是输出流操纵器。它的返回类型是输出流。

因此,如果不进行类型转换就无法通过它。请看这里