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

Pass multiple arguments to stream operator

我有一个 class,让我们用可变模板参数称它为 Sample。此 class 包含一个函数 run(Args... args)。这个 class 还实现了调用此函数的流运算符。

class 看起来像这样:

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

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

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

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

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

我知道我可以只写 make_tuple(1, "msg", 2) 并且它会起作用,但我正在寻找不需要像 make_tuple.

这样的额外函数调用的解决方案

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

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

除非你给编译器一个提示(使用 make_tuple 或传递一个实际的 tuple 变量)它不会知道你的意思并且将无法调用适当的 operator<<().

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

Initializer-lists 未在操作员端启用。

它们在 right-hand 端未启用,因为它们在 left-hand 端未启用,并且它们在 left-hand 端未启用,因为那也会构成对解析器来说是一个巨大的挑战。

至于这样做的原因,Stroustrup 和 Dos Reis 在 2007 年发表的 draft/discussion paper N2215 对 [=28= 的许多问题提供了很多见解] 在各种情况下。具体来说,有一个关于二元运算符的部分(第 6.2 节):

Consider more general uses of initializer lists. For example:

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

When we consider operators as syntactic sugar for functions, we naturally consider the above equivalent to

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

It is therefore natural to extend the use of initializer lists to expressions. There are many uses where initializer lists combined with operators is a “natural” notation.
However, it is not trivial to write a LR(1) grammar that allows arbitrary use of initializer lists. A block also starts with a { so allowing an initializer list as the first (leftmost) entity of an expression would lead to chaos in the grammar.
It is trivial to allow initializer lists as the right-hand operand of binary operators, in subscripts, and similar isolated parts of the grammar. The real problem is to allow ;a={1,2}+b; as an assignment-statement without also allowing ;{1,2}+b;. We suspect that allowing initializer lists as right-hand, but nor [sic] as left-hand arguments to most operators is too much of a kludge, [...]