Передать несколько аргументов оператору потока

У меня есть класс, давайте назовем это 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;
}
};

Теперь я хочу использовать потоковый оператор для объединения нескольких вызовов, передавая аргументы через инициализацию кортежей кортежей:

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

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

Я знаю, я мог бы просто написать make_tuple(1, "msg", 2) и это будет работать, но я ищу решение, которое не требует дополнительных вызовов функций, таких как make_tuple,

Есть ли способ реализовать такую ​​функцию, чтобы я мог передавать аргументы в фигурных скобках (или, возможно, через запятую, перегружая оператор запятой)?

1

Решение

Когда вы используете линию s << {1, "msg", 2} << {1, "msg", 2}; он не предоставляет компилятору C ++ достаточно информации, чтобы понять, что вы подразумеваете под этими списками инициализаторов.

Если вы не дадите подсказку компилятору (используйте make_tuple или передать фактический tuple переменная) он не будет знать, что вы имеете в виду, и не сможет вызвать соответствующий operator<<(),

Похоже, вам не повезло. Это невозможно сделать так, как ваш вопрос опубликован.

2

Другие решения

Списки инициализаторов не включены на стороне оператора.

Они не включены с правой стороны, потому что они не включены с левой стороны, и они не включены с левой стороны, потому что это стало бы слишком большой проблемой для анализаторов.

Что касается причины этого, черновик / дискуссионный документ N2215 Stroustrup и Dos Reis из 2007 года дают глубокое понимание многих проблем со списками инициализаторов в различных контекстах. В частности, есть раздел о бинарных операторах (раздел 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;, Мы подозреваем, что допускать списки инициализаторов в качестве правосторонних, но [sic] в качестве левых аргументов для большинства операторов — слишком много пустяков, […]

2

По вопросам рекламы [email protected]