c++ - 不能将 typeof(std::endl) 作为模板参数?

标签 c++ c++11 variadic-templates

所以,我试着写一个这样的函数:

void append_to_stream(std::ostream &stream)
{ }

template <typename T, typename... Args>
void append_to_stream(std::ostream &stream, T first, Args&&... rest)
{
  stream << first;
  append_to_stream(stream, rest...);
}

并这样调用它:

append_to_stream(stream, 
                 std::endl,
                 std::endl);

但这行不通。我收到一条错误消息,指出该函数“参数过多”。我已经将范围缩小到我知道 std::endl 的程度是有罪的——可能是因为它是一个函数。我设法通过声明一个名为 endl 的结构来“解决”这个问题并定义 <<operator为此,它只需调用 std::endl .这有效,但感觉不是特别好。是否不能接受 std::endl 作为模板参数?该函数适用于其他类型。

编辑:这里是错误:

src/log/sinks/file_sink.cpp:62:21: error: too many arguments to function ‘void log::sinks::append_to_stream(std::string&, Args&& ...) [with Args = {}, std::string = std::basic_string<char>]’

更新

试图让编译器推断出正确的模板参数@MooingDuck 建议可以使用以下形式的函数:

  template<class e, class t, class a> 
  basic_ostream<e,t>&(*)(basic_ostream<e,t>&os) get_endl(basic_string<e,t,a>& s) 
  {
return std::endl<e,t>;
  }

但是,这不会编译。

错误:

src/log/sinks/file_sink.cpp:42:28: error: expected unqualified-id before ‘)’ token
src/log/sinks/file_sink.cpp:42:53: error: expected initializer before ‘get_endl’

有什么想法吗?为了编译这个,我添加了 using namespace std;

最佳答案

std::endl 是模板,不是函数,编译器无法解析要使用哪个 endl

尝试:

append_to_stream(std::cout,
             std::endl<char, std::char_traits<char>>,
             std::endl<char, std::char_traits<char>>);

或者,MooingDuck 的解决方案(更正):

template<class e, class t, class a> //string version
std::basic_ostream<e, t>& (*get_endl(const std::basic_string<e, t, a>&))
    (std::basic_ostream<e, t>& )
{ return std::endl<e,t>; } 

template<class e, class t> //stream version
std::basic_ostream<e, t>& (*get_endl(const std::basic_ostream<e, t>&))
    (std::basic_ostream<e, t>& )
{ return std::endl<e,t>; }

int main () {
  std::ostream& stream = std::cout;
  append_to_stream(stream,
                 get_endl(stream),
                 get_endl(stream));
}

这是 get_endl 解决方案,通过 C++11 decltype 功能简化:

template<class e, class t, class a> //string version
auto get_endl(const std::basic_string<e, t, a>&)
  -> decltype(&std::endl<e,t>)
{ return std::endl<e,t>; }

template<class e, class t> //stream version
auto get_endl(const std::basic_ostream<e,t>&)
  -> decltype(&std::endl<e,t>)
{ return std::endl<e,t>; }

int main () {
  std::ostream& stream = std::cout;
  append_to_stream(stream,
                 get_endl(stream),
                 get_endl(stream));
}

关于c++ - 不能将 typeof(std::endl) 作为模板参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10015897/

相关文章:

c++ - 如何编写写入/var/log/myapp 目录的 C/C++ 应用程序?

c++ - Clang vs GCC vs MSVC 模板转换运算符——哪个编译器是对的?

c++11 - GCC、Clang 和 MSVC 中的可变参数模板-模板参数和 sizeof 差异 - 谁是对的?

c++ - 使用 boost::spirit 解析 Newick 语法

c++ - 在 C++11 中实现看门狗定时器

c++ - 用于确定类是否输出可流式意外输出的元程序

c++ - 为什么原始 curl 构造函数 {} 不返回右值?

c++ - 可变参数构造函数中的 SFINAE

c++ - 支持逗号和错误信息的自定义 `assert`宏

c++ - 使用 C++ 在二叉搜索树中存储值