Скобка инициализирует кортеж в аргументе функции - PullRequest
0 голосов
/ 29 марта 2020

Основная проблема в том, что я хочу написать функцию, которая принимает два набора аргументов переменной длины.

Абстракция, для которой я решил go, состоит в том, чтобы эмулировать следующий синтаксис вызова:

f({a,b,c},x,y);

Если a, b и c имеют одинаковый тип, это можно сделать для работы с

template <typename X, typename... A>
void f(std::initializer_list<X> xs, A&&... as) { . . . }

Но аналогичное определение функции с std::tuple вместо std::initializer_list не позволяет использовать желаемый синтаксис.

template <typename... X, typename... A>
void f(const std::tuple<X...>& xs, A&&... as) { . . . }

Есть ли какой-нибудь прием, который я могу использовать, чтобы типы в первой группе были разнородными?

Приложение: В общем, я не знаю заранее размер X....

Приложение 2. Кто-нибудь знает техническую причину, по которой инициализатор с фигурными скобками работает для std::tuple t{a,b,c}, но не в контексте аргумента шаблона? Это потому, что в моем примере xs не расширен X...?

1 Ответ

1 голос
/ 29 марта 2020

Нет, в настоящее время это невозможно с желаемым синтаксисом. Список инициализаторов может быть выведен только в массив или std::initializer_list, оба однородных типа.

Это специальное правило. Список инициализаторов не имеет типа и просто не может быть выведен ни к чему другому. Если параметр функции не является массивом или std::initializer_list, то параметром, для которого был задан список инициализатора, становится невыгруженный контекст , и вычет аргумента шаблона будет игнорироваться.

В частности, невозможно вывести аргумент шаблона класса в параметре функции, чтобы определить тип из списка инициализированных фигурных скобок, как это можно сделать в определении переменной начиная с C ++ 17. Такая возможность не была добавлена ​​в язык.

В принципе, вы могли бы разрешить конечное число различных типов, используя, например, массив std::variant в качестве параметра, но это будет разрешено для типа только во время выполнения и вряд ли это то, что вы хотите.

Вам нужно либо добавить имя типа или вызов функции в фигурные скобки списка инициализатора, как в

f(std::forward_as_tuple(a, b, c), x, y)

, либо вместо этого можно использовать тип тега чтобы указать конец первого пакета в плоском списке аргументов:

f(a, b, c, tag, x, y)

Тег можно затем обнаружить с помощью некоторой работы с шаблоном.

...