如何使用已知的非默认构造函数实例化未知大小的可变参数元组

How do I instantiate a variadic tuple of unknown size with known non-default constructors?

本文关键字:变参 元组 参数 未知 构造函数 何使用 默认 实例化      更新时间:2023-10-16

假设我有std::tuple种类型。我不知道它包含多少或什么类型,但我知道每个元素都有一个接受单个参数的构造函数。

为了解决这个问题,假设参数是整数5但该值直到运行时才知道

如何构造这样的元组?

这是我到目前为止的尝试,

它尝试使用编译时常量构造元组(不是我想要的,但它是一个起点):

#include <tuple>                                                                 
struct Fixture                                                                   
{
    // I don't know the value until runtime, so this is a poor
    // example anyway.
    template <typename T>                                                        
    struct Unpack                                                                
    {                                                                            
        static const int value = 5;                                    
    };                                                                           
    template <typename... T>                                                     
    struct Y                                                                     
    {                                                                            
        Y()                                                                      
        :   
            // this needs to be a runtime value                                                                     
            tup(Unpack<T>::value...)                                             
        {                                                                        
        }                                                                        
        std::tuple<T...> tup;                                                    
    };                                                                           
    Y<int, double, unsigned /*, some other classes */> y;                                                          
};                                                                               

除了丑陋(Unpack类不应该是必需的)并且只使用编译时已知的常量值之外,这也会导致链接器错误:

建筑的未定义符号x86_64:
"Fixture::Unpack::value",引用自: Fixture::Y::Y() in testTest.cpp.o ld:找不到架构x86_64符号 叮当:错误:链接器命令失败 使用退出代码 1(使用 -v 查看调用)

标准库或 Boost 中是否有一些元编程魔法可以完成这项工作,最好是使用更简洁的语法?我觉得类似std::integer_sequence的东西可能会帮助我,但我不知道怎么做!

诀窍是构造一个引用可变参数包的表达式,但其值是你的参数。扩展后,它将成为参数的重复。逗号运算符做得很好:

template <typename... T>
struct Y
{
    Y(int value)
    : tup((void(sizeof(T)), value)...)
    { }
    std::tuple<T...> tup;
};

void的强制转换是显式丢弃逗号左侧的值。 sizeof(T)可以替换为引用T的任何内容。

删除值上的常量,您可以使用这个

template<typename T>
T Fixture::Unpack<T>::value{};

定义每个可能的"解包类型"。

然后,您可以在运行时使用类似的东西来更新值:

int main() {
    std::cin >> Fixture::Unpack<int>::value >> Fixture::Unpack<double>::value;
    Fixture f;
    std::cout << std::get<0>(f.y.tup) << " " << std::get<1>(f.y.tup);
}

现场示例