默认构造 std::variant 中的所有类型并将它们放入 std::vector
Default-construct all the types in a std::variant and put them in a std::vector
我如何制作一个 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());
这里是使用可变参数模板的示例解决方案。
#include <vector>
#include <variant>
#include <iostream>
#include <typeinfo>
struct TypeA {};
struct TypeB {};
struct TypeC {};
using TaskVariant = std::variant<TypeA, TypeB, 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
1.Solution: 您可以将 variant 转换为 tuple 然后使用 C++17 std ::申请:
#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.Solution: 使用 make_index_sequence, variant_alternative_t 和 variant_size_v(所有 C++17)(感谢 @s d 指出 variant_alternative_t,但我通过使用 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, TypeB, 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, TypeB, 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 小时前击败了我 ^^
在类型上使用模板折叠(逗号运算符)怎么样?
#include <variant>
#include <vector>
struct TypeA {};
struct TypeB {};
struct TypeC {};
using TaskVariant = std::variant<TypeA, TypeB, TypeC>;
template <typename ... Ts>
void addTypes (std::vector<std::variant<Ts...>> & vec)
{ (vec.push_back(Ts{}), ...); }
int main()
{
std::vector<TaskVariant> vec;
addTypes(vec);
}
我如何制作一个 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());
这里是使用可变参数模板的示例解决方案。
#include <vector>
#include <variant>
#include <iostream>
#include <typeinfo>
struct TypeA {};
struct TypeB {};
struct TypeC {};
using TaskVariant = std::variant<TypeA, TypeB, 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
1.Solution: 您可以将 variant 转换为 tuple 然后使用 C++17 std ::申请:
#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.Solution: 使用 make_index_sequence, variant_alternative_t 和 variant_size_v(所有 C++17)(感谢 @s d 指出 variant_alternative_t,但我通过使用 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, TypeB, 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, TypeB, 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 小时前击败了我 ^^
在类型上使用模板折叠(逗号运算符)怎么样?
#include <variant>
#include <vector>
struct TypeA {};
struct TypeB {};
struct TypeC {};
using TaskVariant = std::variant<TypeA, TypeB, TypeC>;
template <typename ... Ts>
void addTypes (std::vector<std::variant<Ts...>> & vec)
{ (vec.push_back(Ts{}), ...); }
int main()
{
std::vector<TaskVariant> vec;
addTypes(vec);
}