Is it possible to use a macro or something similar to create instances of a template class and generate the code that then adds the created variables to a std::vector
that uses std::variant
?
Consider this example:
#include <memory>
#include <variant>
#include <vector>
template <typename... Ts>
class Foo
{
};
int main()
{
// These definitions of Foo shall be produced by the macro
auto foo1 = std::make_shared<Foo<int, int, int>>(Foo<int, int, int>());
auto foo2 = std::make_shared<Foo<int, int>>(Foo<int, int>());
// The variants shall be done with respect to the instantiations of Foo
std::vector<std::variant<decltype(foo1), decltype(foo2)>> objects;
return 0;
}
foo1 and foo2 two create two types of the class Foo since they are using different template parameters. Therefore, the std::vector<std::variant<...>>
objects is able to hold two variants. If one would define a foo3 with a different type than the two before, it should come with three variants accordingly. Is this possible?
Or a macros in general not capable of handling data types as input?
In general, variables of the form foo1
, foo2
, ..., fooN
should be in a container instead. An array won't work because the types are different, but a tuple will.
A helper function can help you call make_shared
for each type:
template<typename... InputTypes, typename Factory>
constexpr auto map_types(Factory&& f) {
return std::make_tuple(f(std::type_identity<InputTypes>{})...);
}
auto foos = map_types<
Foo<int, int, int>,
Foo<int, int>
>([]<class T>(std::type_identity<T>) {
return std::make_shared<T>();
});
// foo1 -> std::get<0>(foos)
// foo2 -> std::get<1>(foos)
// Or for convenience
auto& [ foo1, foo2 ] = foos;
And the type of foos
will be std::tuple<std::shared_ptr<Foo<int, int, int>>, std::shared_ptr<Foo<int, int>>>
, which you can programmatically transform into your variant type:
using variant_type = decltype([]<typename... T>(std::tuple<T...> const&) -> std::variant<T...> { std::unreachable(); }(foos));
std::vector<variant_type> objects;
If you wanted to add or remove any types, you only have to change the template parameters given to map_types<...>
.