有没有办法将 std::variant 与任意多个定义的类型一起使用?
is there a way to use std::variant with arbitrarily many defined types?
我刚刚开始学习使用 std::variant
并且我想声明一个类型列表(原则上)由任意多个我的用户定义类型组成。即,类似
template<typename T>
struct MyType{
T x;
};
template<typename T, int N>
MyClass{
public:
MyType<T> y;
int z = N;
double w;
MyClass(double b){
w = b;
}
};
template<typename T>
using my_type_list = std::variant<
MyClass<T,1>, MyClass<T,289>, MyClass<T,13>, ...., MyClass<T,5001>
>;
template<typename T>
std::vector<my_type_list> my_big_list = {
MyClass<T,1> { 2.0 },
MyClass<T,1> { 3.0 },
MyClass<T,289> { 9.4 },
MyClass<T, 13> { 1.3 },
MyClass<T, 5001> {2.5},
MyClass<T, 5001> {3.2},
..... etc....
};
但是整数 N
原则上可以是任何东西。
有什么办法可以做到这一点吗?
您表示您希望使用另一个模板参数来指定变体中值的数量。在那种情况下,使用它构造一个 std::integer_sequence,然后使用它来创建您的变体类型列表是一件简单的事情。
#include <variant>
#include <type_traits>
#include <utility>
template<typename T>
struct MyType{
T x;
};
template<typename T, int N>
class MyClass{
MyType<T> y;
int z = N;
};
template<typename T, typename sequence> struct my_type_helper;
template<typename T, int ...N>
struct my_type_helper<T, std::integer_sequence<int, N...>> {
typedef std::variant<MyClass<T, N>...> variant_t;
};
template<typename T, int N>
using my_type=
typename my_type_helper<T, std::make_integer_sequence<int, N>>::variant_t;
static_assert(std::is_same_v<std::variant<MyClass<int, 0>,
MyClass<int, 1>,
MyClass<int, 2>>,
my_type<int, 3>>);
static_assert
证明my_type<int, 3>
等价于std::variant<MyClass<int, 0>, MyClass<int, 1>, MyClass<int, 2>>
.
P.S。 int z = N;
应该是 constexpr int z=N;
.
您可以使用 std::index_sequence
创建一系列编译时索引,然后使用它来创建 std::variant
,这些索引作为非类型模板参数的可变参数包。
template<typename T, std::size_t ...Is>
auto my_type_list_impl(std::index_sequence<Is...>)
-> std::variant<MyClass<T, Is + 1>...>; // no definition needed, we just need the return type
template<typename T, int N>
using my_type_list
= decltype(my_type_list_impl<T>(std::make_index_sequence<N>{}));
这是一个demo
我刚刚开始学习使用 std::variant
并且我想声明一个类型列表(原则上)由任意多个我的用户定义类型组成。即,类似
template<typename T>
struct MyType{
T x;
};
template<typename T, int N>
MyClass{
public:
MyType<T> y;
int z = N;
double w;
MyClass(double b){
w = b;
}
};
template<typename T>
using my_type_list = std::variant<
MyClass<T,1>, MyClass<T,289>, MyClass<T,13>, ...., MyClass<T,5001>
>;
template<typename T>
std::vector<my_type_list> my_big_list = {
MyClass<T,1> { 2.0 },
MyClass<T,1> { 3.0 },
MyClass<T,289> { 9.4 },
MyClass<T, 13> { 1.3 },
MyClass<T, 5001> {2.5},
MyClass<T, 5001> {3.2},
..... etc....
};
但是整数 N
原则上可以是任何东西。
有什么办法可以做到这一点吗?
您表示您希望使用另一个模板参数来指定变体中值的数量。在那种情况下,使用它构造一个 std::integer_sequence,然后使用它来创建您的变体类型列表是一件简单的事情。
#include <variant>
#include <type_traits>
#include <utility>
template<typename T>
struct MyType{
T x;
};
template<typename T, int N>
class MyClass{
MyType<T> y;
int z = N;
};
template<typename T, typename sequence> struct my_type_helper;
template<typename T, int ...N>
struct my_type_helper<T, std::integer_sequence<int, N...>> {
typedef std::variant<MyClass<T, N>...> variant_t;
};
template<typename T, int N>
using my_type=
typename my_type_helper<T, std::make_integer_sequence<int, N>>::variant_t;
static_assert(std::is_same_v<std::variant<MyClass<int, 0>,
MyClass<int, 1>,
MyClass<int, 2>>,
my_type<int, 3>>);
static_assert
证明my_type<int, 3>
等价于std::variant<MyClass<int, 0>, MyClass<int, 1>, MyClass<int, 2>>
.
P.S。 int z = N;
应该是 constexpr int z=N;
.
您可以使用 std::index_sequence
创建一系列编译时索引,然后使用它来创建 std::variant
,这些索引作为非类型模板参数的可变参数包。
template<typename T, std::size_t ...Is>
auto my_type_list_impl(std::index_sequence<Is...>)
-> std::variant<MyClass<T, Is + 1>...>; // no definition needed, we just need the return type
template<typename T, int N>
using my_type_list
= decltype(my_type_list_impl<T>(std::make_index_sequence<N>{}));
这是一个demo