Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

Error: no matching function for call to 'LOG_ERROR(const char [14], int&, )' LOG_ERROR("Sum of x+y = ", z, std::endl);

note: candidate: 'void LOG_ERROR()' inline void LOG_ERROR() {

note: candidate expects 0 arguments, 3 provided

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

like image 892
eneski Avatar asked Aug 16 '18 07:08

eneski


2 Answers

Long story short - std::endl is function template which template arguments can't be deduced while passing. 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.

like image 197
bartop Avatar answered Sep 22 '22 01:09

bartop


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, i.e., the template arguments of std::endl can still be deduced when it's <<'d into the stream.

like image 20
lubgr Avatar answered Sep 20 '22 01:09

lubgr