不能将typeof(std::endl)作为模板参数
Cannot have typeof(std::endl) as template parameter?
所以,我试图写一个这样的函数:
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));
}
通过强制转换解决重载比指定模板参数或定义一个全新模板(!)容易得多。
typedef std::ostream & (&omanip_t)( std::ostream & );
append_to_stream(stream,
static_cast< omanip_t >( std::endl ),
static_cast< omanip_t >( std::endl ) );
这将适用于所有操纵器,而某些操纵器可以采用不同的模板,例如,如果用户提供。
此外,您应该通过完全转发或常量引用来传递T first
。先向前,然后按价值传递,这没有多大意义。此外,如果不调用std::forward
,右值参数将按值传递……按照惯例,它将是
template <typename T, typename... Args>
void append_to_stream(std::ostream &stream, T &&first, Args&&... rest)
{
stream << std::forward< T >( first );
append_to_stream(stream, std::forward< Args >( rest ) ... );
}
http://ideone.com/cw6Mc
相关文章:
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 使用不带参数的函数访问结构元素
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 如何使用Luacneneneba API正确读取字符串和表参数
- 在派生函数中指定void*参数
- 可变参数模板函数:调用没有匹配函数,std::endl
- 为什么在语句"std::cout << std::endl;"中使用时需要命名空间限定,给定依赖于参数的查找?
- std::endl 和可变参数模板
- endl 是一个方法,如果是,它可以接受参数
- 不能将typeof(std::endl)作为模板参数