В C++ можно создать карту времени компиляции строковых имен типов в типы. Я знаю, что сами типы не могут быть сопоставлены, но можем ли мы, например, сопоставить метафункции шаблона, которые предоставляют тип?
В частности, мы могли бы, например, иметь одну метафункцию шаблона варада, которая принимает некоторый начальный набор типов, а затем во время компиляции создает статическую карту, используя, например, выражение свертки, чтобы во время выполнения мы могли получить доступ к открытому типу и использовать его в качестве параметра шаблона. в другую функцию, что-то вроде этого
TypeMapper::Map["Type1"]::type
Итак, во время выполнения, если бы мы хотели, например, выполнить определенную шаблонную функцию, мы могли бы сделать
MyTypeProcessor<TypeMapper::Map["Type1"]::type>();
Если это невозможно из-за ограничений языка, мне интересно, какое конкретно ограничение, потому что по отдельности я считаю, что отдельные части идеи в некоторой степени осуществимы, но я просто не уверен, как это сделать, поэтому, если я что-то здесь упускаю помощь будет очень признательна. Я все еще новичок в этом, поэтому могу некоторые вещи неправильно понимать.
Вы же не пытаетесь создать какой-то код отражения или сериализации? Потому что сериализация, как известно, сложна в реализации, а отражение (во время выполнения) на самом деле не соответствует философии проектирования C++. C++ — это язык, который очень ориентирован на фазу компиляции. Итак, вместо описания того, КАК вы хотите что-то делать, можете ли вы также объяснить, ЧЕГО вы пытаетесь достичь?
Этот синтаксис не может работать. Map
должно быть выражением (а не типом), как и Map["Type1"]
, поэтому Map["Type1"]::type
не может быть допустимым. Но мы можем это упростить! Поскольку это выражение предположительно отображается в Type1
во время компиляции, мы можем просто заменить его на Type1
.
Типы никогда не могут определяться значениями времени выполнения. Скорее всего, вы делаете это неправильно.
Это возможно с другим синтаксисом.
Нам бы хотелось, чтобы строковые литералы можно было использовать в качестве нетиповых параметров шаблона, но в настоящее время C++ этого не позволяет. Итак, давайте создадим замену, которая будет столь же хороша функционально, но менее удобна.
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);
}
Теперь make_ct_string("foo")
возвращает значение, которое можно использовать как NTTP. Мы можем использовать его для пометки типов строками.
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; }
};
Отсюда мы можем использовать такие типы, как tagged_with_string<make_ct_string("foo")>
.
using tagged_abc = tagged_with_string<make_ct_string("abc")>;
constexpr auto abc_tag = tagged_abc::tag();
Вы можете построить карту следующим образом:
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>);
Обратите внимание: я не знаю, хотите ли вы этого, потому что здесь ничто не ожидает времени выполнения. Но это определенно то, что я хочу для одного из моих любимых проектов.
Для чего тебе это нужно? Прежде всего, вы уверены, что хотите, чтобы это происходило во время компиляции? Это означало бы, что у каждого TU будет своя собственная карта, а не одна глобальная карта.