Why is std::endl generating this cryptic error message?

和自甴很熟 提交于 2019-12-05 03:30:09

std::endl is a function template. When it is used, its template parameters have to be explicitly specified or deduced by the compiler.

std::ostream has an overload:

basic_ostream<charT,traits>& operator<<(
    basic_ostream<charT,traits>& (*pf) (basic_ostream<charT,traits>&) );

When we use

std::cout << std::endl;

the compiler deduces the types to be used for std::endl. Since you don't have the ability to fall back on automatic type deduction when calling print, you have to be explicit about which version of std::endl you want to use.

The following should work:

print(std::cout, "The answer is ", 42, std::endl<char, std::char_traits<char>>);

Update

I used the following stripped down code to track the issue:

#include <iostream>

namespace detail
{
   template <class T>
      void print(std::ostream& stream, const T& item)
      {
         stream << item;
      }
}

int main()
{
    // detail::print(std::cout, std::endl);
    detail::print(std::cout, std::endl<char, std::char_traits<char>>);
}

I think this is because template type deduction fails if you are passing a function template. It can't deduce the parameters to instantiate endl with.

Note that the definition of endl is:

template <class charT, class traits> 
basic_ostream<charT,traits>& endl (basic_ostream<charT,traits>& os);

Simpler example:

template<class U> void func(U &u) { }

template<class T>
void print(const T &item) { }

int main()
{
print(func);    // error: matching function for call to 'print(<unresolved overloaded function type>)'
}

Your error messages come about because it tries various ways to match your function call to the parameter pack but none of them worked.

You could avoid the problem by defining a simple endl yourself (Live Demo):

constexpr struct endl_ {
    friend std::ostream& operator << (std::ostream& os, const endl_&) {
        os << '\n'; // << std::flush;
        return os;
    }
} endl;

template <class... Args>
void print(std::ostream& stream, Args&&... args)
{
    std::stringstream ss;
    std::initializer_list<int>{0, (void(ss << std::forward<Args>(args)), 0)...};
    stream << ss.rdbuf();
}

int main()
{
    print(std::cout, "The answer is ", 42, endl);
    //error: no matching function for call to 'print'
    print(std::cout, "The answer is NOT ", 13, endl);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!