c++ - 在函数调用时从异构初始化列表构建元组

标签 c++ initialization tuples c++17 aggregate-initialization

考虑以下函数

template <class... T, class... U>
void f(std::tuple<T...> t, std::tuple<U...> u)
{
    std::cout << sizeof...(T) << " " << sizeof...(U) << std::endl;
}

int main(int argc, char* argv[]) 
{
    f({3, 3.5, "Hello World!"}, {'a', std::string("b")}); // Fails
    return 0;
}

在 C++17 中是否有任何方法可以修改函数签名,以便标记为“失败”的行可以工作? (保持那条线不变)。

最佳答案

我的猜测是简短的回答是否定的
粗略地说,{ args... } 不是元组,您会遇到与 C++14 中相同的推导和转换问题。


话虽如此,在 C++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;
}

通用 lambda 为您创造了魔力,您可以通过额外的间接级别获得与您想要的类似的东西(这通常有助于解决任何问题)。


在 C++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")});

无论如何,您为此牺牲了可读性,从我的角度来看,这不值得。

关于c++ - 在函数调用时从异构初始化列表构建元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44361779/

相关文章:

c++ - C1x 从 C++ 继承了什么?

c++ - 具有三元返回和短路的运算符

c - 为什么 main 中未初始化的局部变量在 c 中为零(不是垃圾)?

Delphi 单元初始化并不总是被调用

Typescript:对象类型到数组类型(元组)

python - 在元组列表中按字母对数字求和

c++ - 错误, “include/Trading_GenericTemplate.h:37: error: expected constructor, destructor, or type conversion before â=â token”

c++ - Xcode 未运行最新版本的 OpenGL,这会导致编译错误

c++ - 使用初始值设定项列表中较早初始化的成员来初始化成员是否安全?

arrays - 使用元组进行 Scala 数组切片