问题描述
我如何制作一个std::vector
,其中包含std::variant
中包含的所有类型的默认构造的实例?
using TaskVariant = std::variant<TypeA,TypeB,TypeC>;
std::vector<TaskVariant> variants;
// I'd like to do this in a loop
variants.push_back(TypeA());
variants.push_back(TypeB());
variants.push_back(TypeC());
解决方法
1。解决方案::您可以将变体转换为元组,然后使用C ++ 17 std :: apply :
#include <variant>
#include <iostream>
#include <string>
#include <vector>
#include <tuple>
using namespace std;
template <typename... Types>
struct ToTuple;
template <typename... Types>
struct ToTuple<variant<Types...>>
{
using type = tuple<Types...>;
};
struct TypeA {};
struct TypeB {};
struct TypeC {};
using TaskVariant = std::variant<TypeA,TypeB,TypeC>;
int main()
{
vector<TaskVariant> vec;
apply([&vec](auto&&... args) {(vec.push_back(args),...); },ToTuple<TaskVariant>::type{});
}
编辑:
2。解决方案::使用 make_index_sequence , variant_alternative_t 和 variant_size_v (所有C ++ 17)(谢谢)指向 variant_alternative_t 来 @sd ,但我通过使用 make_index_sequence 而不是递归来修改了示例):
#include <variant>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct TypeA {};
struct TypeB {};
struct TypeC {};
using TaskVariant = std::variant<TypeA,TypeC>;
template <size_t... Idx>
void fill_vec(vector<TaskVariant>& vec,index_sequence<Idx...> idx)
{
(vec.push_back(variant_alternative_t<Idx,TaskVariant>{}),...);
}
int main()
{
vector<TaskVariant> vec;
fill_vec(vec,make_index_sequence<variant_size_v<TaskVariant>>{});
}
,
另一个解决方案
#include <iostream>
#include <variant>
#include <vector>
struct TypeA {
int a;
TypeA() : a{0} {std::cout<<"A"<<std::endl;};
};
struct TypeB {
int b;
TypeB() : b{0} {std::cout<<"B"<<std::endl;};
};
struct TypeC {
int c;
TypeC() : c{0} {std::cout<<"C"<<std::endl;};
};
using TaskVariant = std::variant<TypeA,TypeC>;
template<class var,std::size_t I = 0>
void autofill(std::vector<var>& vec){
if constexpr(I < std::variant_size_v<var>){
vec.push_back(std::variant_alternative_t<I,var>{});
autofill<var,I + 1>(vec);
}
}
int main() {
std::vector<TaskVariant> variants;
autofill(variants);
}
编辑:完全忘记了C ++ 17中的此功能。
template<class... VA> //VA for variant alternatives
void autofill(std::vector<std::variant<VA...> >& vec) {
(...,vec.emplace_back(VA{}));
}
https://en.cppreference.com/w/cpp/language/fold 编辑2:好像@max在大约4小时前击败了我^^
,使用类型的模板折叠(逗号运算符)怎么样?
@Override
,
这里使用可变参数模板的示例解决方案。
#include <vector>
#include <variant>
#include <iostream>
#include <typeinfo>
struct TypeA {};
struct TypeB {};
struct TypeC {};
using TaskVariant = std::variant<TypeA,TypeC>;
template <class T>
void addValue(std::vector<TaskVariant> & v)
{
v.push_back(T());
std::cout << "adding " << typeid(T).name() << " default ctor\n";
}
template <class T,class V,class... Args>
void addValue(std::vector<TaskVariant> & v)
{
addValue<T>(v);
addValue<V,Args...>(v);
}
template <class... Args>
void addValues(std::vector<std::variant<Args...>> & v)
{
addValue<Args...>(v);
}
int main()
{
std::vector<TaskVariant> variants;
addValues(variants);
}
输出为:
adding 5TypeA default ctor
adding 5TypeB default ctor
adding 5TypeC default ctor