Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/wordpress/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 元组的运行时索引_C++_C++11_Templates_Reflection_Tuples - Fatal编程技术网

C++ 元组的运行时索引

C++ 元组的运行时索引,c++,c++11,templates,reflection,tuples,C++,C++11,Templates,Reflection,Tuples,假设我有一个变量构造函数,它是一个用变量泛型lambda表示的构造函数元组 //构造函数的类型 使用type_tuple=std::tuple; //获取类型为“”的构造函数的元组(可变泛型lambda) 自动构造函数=execute_all_t(get_construct()); //有关execute_all_t和get_构造的定义,请参见底部的链接。 我可以使用以下命令实例化对象: //使用构造函数创建一个对象,其中0是元组中ClassA的索引。 ClassA=std::get(构造函数

假设我有一个变量
构造函数
,它是一个用变量泛型lambda表示的构造函数元组

//构造函数的类型
使用type_tuple=std::tuple;
//获取类型为“”的构造函数的元组(可变泛型lambda)
自动构造函数=execute_all_t(get_construct());
//有关execute_all_t和get_构造的定义,请参见底部的链接。
我可以使用以下命令实例化对象:

//使用构造函数创建一个对象,其中0是元组中ClassA的索引。
ClassA=std::get(构造函数)(/*参数表示ClassA*/)的任何构造函数;
是否可以在运行时使用下面的
magic\u get
索引该类型

auto-obj=magic_-get(构造函数,0)(/*类的任何构造函数的参数*/);
//也许obj可以是std::variant,它包含ClassA的对象?
Edit:理想情况下,
obj
应该是
ClassA
的一个实例。如果不可能,我可以接受
obj
成为
std::variant

请查看最小可复制示例:



类似的问题:.

您可能让运行时获得return
std::variant
,类似于:

template <typename ... Ts, std::size_t ... Is>
std::variant<Ts...> get_impl(std::size_t index,
                             std::index_sequence<Is...>,
                             const std::tuple<Ts...>& t)
{
    using getter_type = std::variant<Ts...> (*)(const std::tuple<Ts...>&);
    getter_type funcs[] = {+[](const std::tuple<Ts...>& tuple)
                            -> std::variant<Ts...>
                            { return std::get<Is>(tuple); } ...};

    return funcs[index](t);
}

template <typename ... Ts>
std::variant<Ts...> get(std::size_t index, const std::tuple<Ts...>& t)
{
    return get_impl(index, std::index_sequence_for<Ts...>(), t);
}

您可能会让运行时获得return
std::variant
,类似于:

template <typename ... Ts, std::size_t ... Is>
std::variant<Ts...> get_impl(std::size_t index,
                             std::index_sequence<Is...>,
                             const std::tuple<Ts...>& t)
{
    using getter_type = std::variant<Ts...> (*)(const std::tuple<Ts...>&);
    getter_type funcs[] = {+[](const std::tuple<Ts...>& tuple)
                            -> std::variant<Ts...>
                            { return std::get<Is>(tuple); } ...};

    return funcs[index](t);
}

template <typename ... Ts>
std::variant<Ts...> get(std::size_t index, const std::tuple<Ts...>& t)
{
    return get_impl(index, std::index_sequence_for<Ts...>(), t);
}

这也许可以做得更好,但根据您在评论中的要求,这里有一个尝试

需要C++17,在Clang上工作,但在GCC上提供了一个

但是,它确实需要使构造函数SFINAE友好,否则无法检查是否可以调用它:

所以使用

return[](auto…args)->decltype(U(args)…){return U(args…);};
而不是

return[](自动…args){返回U(args…;};

给定参数
tup
index
时,此函数的行为如下所示:

它返回一个lambda,当使用参数列表调用该lambda时,它将返回一个
std::variant
,其中包含可能由
std::get(tup)(/*arguments*/)
形式的调用产生的所有类型。在运行时,通过
index
参数决定在返回的变量中实际调用和存储哪一个变量。如果
index
引用的元组元素不能被
std::get(tup)(/*arguments*/)
调用,则会在运行时引发异常

中间lambda可以在以后存储和调用。但是请注意,它保存了对
tup
参数的引用,因此如果不立即调用并放弃该参数,则需要确保该参数超出lambda

#包括
#包括
#包括
#包括
#包括
模板结构常数{
静态constexpr自动值=V;
使用value_type=decltype(value);
constexpr运算符值\u type()const{
返回V;
}
};
模板
inline constexpr auto constant=常量{};
模板
constexpr自动运算符+(常数,常数){
返回常数;
}
模板
结构包裹{
使用类型=T;
constexpr自动运算符+()const{
返回静态_cast(nullptr);
}
};
模板
inline constexpr auto wrap=wrap\u t{};
模板
使用unwrap=typename std::remove\u pointer\u t::type;
模板
自动魔法获取(Tup&&Tup,标准::大小索引){
返回[&tup,index](自动和…参数){
//获取输入元组的大小
constexpr auto size=std::tuple\u size\u v;
//Lambda:检查元组的元素i是否可以使用给定的参数进行调用
constexpr auto是有效的=[](auto i){
返回标准::是发票;
};
//Lambda:获取具有给定参数的tuple的invocable元素i的包装返回类型
constexpr自动结果类型=[](自动i){
返回包装;
};
//递归lambda调用:使用`result\u type`lambda获取包装返回类型的元组
constexpr自动有效\u元组=[=](){
constexpr auto lambda=[=](自动和自动,自动i){
if constexpr(i==大小)
返回std::make_tuple();
否则,如果constexpr(i)有效
返回std::tuple_cat(std::make_tuple(结果类型(i)),self(self,i+常量));
其他的
返回self(self,i+常量);
};
返回λ(λ,常数);
}();
//Lambda:将底层返回类型作为包装变量获取
constexpr自动变量类型=
std::apply([](自动…参数){return wrap;},有效的数组);
/**
*递归lambda:获取匹配函数的所有底层返回类型的变体
*包含具有给定索引和参数的调用函数的返回值。
*
*@param self是lambda本身
*@param tup一组函数
*@param index可从匹配(通过args)函数中选择的索引
*@param i运行索引以达到`index`
*@param j用于在变量中构造的就地索引
*@param args用于调用函数的可变参数
*@return匹配函数的所有底层返回类型的变体
*/
constexpr auto lambda=[=](自动和自、自动和自、标准::大小索引、自动i、自动j、,
自动&&…参数)->展开{
if constexpr(i==大小)
throw std::无效的_参数(“索引太大”);
else if(i==索引){
如果constexpr(是否有效(i)){
返回展开{std::in_place_index,
std::get(tup)(decltype(args)(args)…)};
}否则{
抛出std::无效的_参数(“无效索引”);
}
}否则{
返回self(self,decltype(tup)(tup),索引,i+常量,j+常量,
decltype(args)(args);
}
};
返回lambda(lambda,std::forward(tup),index,constant,
常量,decltype(args)(args);
};
}
在C++20中,您可以通过

  • 使用