将多个参数传递给stream运算符

时间:2017-02-16 15:32:41

标签: c++ template-meta-programming stream-operators

我有一个类,让我们用可变参数模板参数调用它Sample。该类包含函数run(Args... args)。该类还实现了一个调用此函数的流操作符。

该课程如下:

template<typename ...Args>
class Sample
{
    void run(Args... args)
    {
        // do something
    }

    Sample& operator<<(const tuple<Args...>& args)
    {
        run(unpack_somehow(args)...);
        return *this;
    }
};

现在我想使用stream运算符来连接多个调用,方法是通过元组的大括号初始化传递参数:

void main()
{
    Sample<int, string, int> s;

    // doesn't work :(
    s << {1, "msg", 2} << {1, "msg", 2};
}

我知道我可以写make_tuple(1, "msg", 2)并且它会起作用,但我正在寻找一个不需要额外函数调用的解决方案,例如make_tuple

有没有办法实现这样一个功能,我可以在大括号中传递参数(或者通过重载逗号运算符可以通过逗号分隔)?

2 个答案:

答案 0 :(得分:2)

当您使用第s << {1, "msg", 2} << {1, "msg", 2};行时,它不会为C ++编译器提供足够的信息来推断出这些初始值设定项列表的含义。

除非你给编译器提示(使用make_tuple或传递实际的tuple变量),否则它不会知道你的意思,也无法调用相应的{{1 }}

看起来你运气不好。这不能以您的问题发布方式完成。

答案 1 :(得分:2)

初始化程序列表未在操作员一侧启用。

它们未在右侧启用,因为它们未在左侧启用,并且它们未在左侧启用,因为这对解析器构成了太大的挑战。

至于的原因,来自2007年的Stroustrup和Dos Reis的draft/discussion paper N2215提供了很多关于各种上下文中初始化列表的问题的深入见解。具体来说,有一个关于二元运算符的部分(第6.2节):

  

考虑初始化列表的更多常规用法。例如:

v = v+{3,4};
v = {6,7}+v;
     

当我们将运算符视为函数的语法糖时,我们自然会认为上述等价于

v = operator+(v,{3,4});
v = operator+({6,7},v);
     

因此,将初始化列表的使用扩展到表达式是很自然的。初始化列表与运算符结合使用是一种“自然”符号   但是,编写允许任意使用初始化列表的LR(1)语法并非易事。一个块也以{开始允许初始化列表,因为表达式的第一个(最左边)实体会导致语法混乱。
  允许初始化器列表作为二进制运算符的右侧操作数,这是微不足道的   下标和语法的类似孤立部分。真正的问题是允许;a={1,2}+b;作为赋值语句而不允许;{1,2}+b;。我们怀疑允许初始化列表作为右手,但也不是[原文如此]作为大多数运算符的左手参数太多了,[...]