In C++ is it possible to generate a compile time map of stringified type names to types. I am aware types themselves can't be mapped but could we for example map to template metafunctions which expose a type?
So specifically could we for example have one varadic template metafunction which takes some initial set of types, then at compile time constructs a static map using a fold expression for example such that at runtime we could access an exposed type and use it as a template parameter to another function, something like this
TypeMapper::Map["Type1"]::type
So then at runtime if we wanted to for example execute a specific templated function we could do
MyTypeProcessor<TypeMapper::Map["Type1"]::type>();
If this is not possible due to limitations in the language I am curious as to what limitation specifically, because individually I believe the individual parts of the idea are somewhat feasible but I'm just unsure how, so if I'm missing something here any assistance would be greatly appreciated. I am still somewhat new to stuff so I could be misunderstanding some things.
It is possible with a different syntax.
We would like string literals to be usable as non-type template parameters, but currently C++ doesn't allow this. So let's build a replacement that is as good funcvtionally, although less convenient.
template <std::size_t N>
struct ct_string
{
char value[N] = {};
consteval ct_string(const char (&str)[N]) : value{}
{
for (std::size_t i = 0; i < N; ++i) value[i] = str[i];
}
};
template <std::size_t N>
consteval auto make_ct_string(const char (&str)[N])
{
return ct_string<N>(str);
}
Now make_ct_string("foo")
returns a value that is usable as a NTTP. We can use it to tag types with strings.
template <typename K>
struct is_ct_string_t : public std::false_type {};
template <std::size_t N>
struct is_ct_string_t<ct_string<N>> : public std::true_type {};
template <typename K>
concept is_ct_string = is_ct_string_t<K>::value;
template <auto cst> requires is_ct_string<decltype(cst)>
struct tagged_with_string
{
static constexpr auto value = cst;
consteval static std::string_view tag() { return cst.value; }
};
From here we can use types like tagged_with_string<make_ct_string("foo")>
.
using tagged_abc = tagged_with_string<make_ct_string("abc")>;
constexpr auto abc_tag = tagged_abc::tag();
You can build a map this way:
template <auto cst> requires is_ct_string<decltype(cst)> struct Map {}
template <auto cst> requires is_ct_string<decltype(cst)> struct Map {};
template <> struct Map <make_ct_string("int")> { using type = int; };
template <> struct Map <make_ct_string("double")> { using type = double; };
using foo = Map<make_ct_string("double")>::type;
static_assert(std::is_same_v<foo, double>);
Note, I don't know if this is what you want, because nothing whatsoever here waits for run time. But this is definitely what I want for one of my pet projects.