Ответ 1
Я предполагаю, что короткий ответ - это не.
Грубо говоря, { args... }
не является кортежем, и вы подвергаетесь тем же проблемам вычета и конверсии, с которыми вы столкнулись в С++ 14.
Как сказано, в С++ 14/17 вы можете сделать это, чтобы имитировать его (минимальный рабочий пример):
#include<iostream>
#include<string>
#include<tuple>
#include<utility>
template <class... T, class... U>
void f_(std::tuple<T...> t, std::tuple<U...> u) {
std::cout << sizeof...(T) << " " << sizeof...(U) << std::endl;
}
template<typename... T>
auto f(T... t) {
return [tup{std::make_tuple(t...)}](auto... u) {
f_(std::move(tup), std::make_tuple(u...));
};
}
int main(int argc, char* argv[]) {
f(3, 3.5, "Hello World!")('a', std::string("b"));
return 0;
}
Generic lambdas делает магию для вас, и у вас есть что-то похожее на то, что вы хотите, с дополнительным уровнем косвенности (что обычно помогает решить любую проблему).
В С++ 17 вы также можете сделать это:
f(std::tuple{3, 3.5, "Hello World!"}, std::tuple{'a', std::string("b")});
Это имеет типы аргументов, выведенные непосредственно из вызова конструктору, вместо того, чтобы явно указывать их. С помощью псевдонима вы даже можете пойти дальше и уменьшить выражения в точке вызова на что-то вроде этого:
f(T{3, 3.5, "Hello World!"}, T{'a', std::string("b")});
В любом случае вы жертвуете удобочитаемостью для этого, и это не стоит с моей точки зрения.