Сообщение Re: Вопрос по идентификации типа (не RTTI) от 12.04.2019 5:50
Изменено 12.04.2019 7:40 niralex
Re: Вопрос по идентификации типа (не RTTI)
Нашел идею решения своего первоначального вопроса. Может кому-то понадобится...
N>Есть некий конечный набор пользовательских типов и задача их идентифицировать во время выполнения не используя RTTI.
N>Тип идентификатора не важен. Варианты без constexpr известны.
В качестве идентификатора типа берем std::array.
Для шаблонных типов делаем constexpr-конкатенацию array
В результате идентификация типов происходит в compile-time! Мелочь, но приятная
Идентификаторы затем можно сериализовывать, передавать между модулями, сравнивать и т.д.
Буду благодарен, если кто укажет на ошибки, потенциальные проблемы, предложит улучшения, альтернативы.
P.s.
Небольшие косметические улучшения:
Написал функцию MakeTypeId(1), чтобы вместо return array<int8_t,1>{1} писать MakeTypeId(1);
И написал более компактную функцию join, которую можно использовать для объединения не двух, а любого числа array:
N>Есть некий конечный набор пользовательских типов и задача их идентифицировать во время выполнения не используя RTTI.
N>Тип идентификатора не важен. Варианты без constexpr известны.
В качестве идентификатора типа берем std::array.
Для шаблонных типов делаем constexpr-конкатенацию array
// Реализацию функции join берем отсюда(спасибо автору Klemens Morgenstern): https://gist.github.com/klemens-morgenstern/b75599292667a4f53007
template<typename T, std::size_t L, std::size_t R>
constexpr std::array<T, L+R> join(std::array<T, L> rhs, std::array<T, R> lhs) {...};
struct IntCodec
{
static constexpr auto Id() { return array<int8_t,1>{1}; }
// ...
};
struct CharCodec
{
static constexpr auto Id() { return array<int8_t,1>{2}; }
// ...
};
template<typename T>
struct VectorCodec
{
static constexpr auto Id()
{
return join(array<int8_t,1>{3}, T::Id());
}
// ...
};
int main()
{
constexpr auto id1 = IntCodec::Id(); // 1
constexpr auto id1 = VectorCodec<CharCodec>::Id(); // 3,2
constexpr auto id2 = VectorCodec<VectorCodec<IntCodec>>::Id(); // 3,3,1
return 0;
}
В результате идентификация типов происходит в compile-time! Мелочь, но приятная
Идентификаторы затем можно сериализовывать, передавать между модулями, сравнивать и т.д.
Буду благодарен, если кто укажет на ошибки, потенциальные проблемы, предложит улучшения, альтернативы.
P.s.
Небольшие косметические улучшения:
Написал функцию MakeTypeId(1), чтобы вместо return array<int8_t,1>{1} писать MakeTypeId(1);
template <typename... Types>
constexpr auto MakeTypeId(Types&&... t)
{
return std::array<int8_t, sizeof...(Types)>{ std::forward<Types>(t)... };
}
И написал более компактную функцию join, которую можно использовать для объединения не двух, а любого числа array:
template<typename... TArrs>
constexpr auto join(TArrs&&... arrs)
{
std::size_t i = 0;
std::array<int8_t, (arrs.size() + ...)> ret{};
([&](const auto& arr)
{
for (const int8_t& val : arr)
ret[i++] = val;
}(arrs), ...);
return ret;
}
Re: Вопрос по идентификации типа (не RTTI)
Нашел идею решения своего первоначального вопроса. Может кому-то понадобится...
N>Есть некий конечный набор пользовательских типов и задача их идентифицировать во время выполнения не используя RTTI.
N>Тип идентификатора не важен. Варианты без constexpr известны.
В качестве идентификатора типа берем std::array.
Для шаблонных типов делаем constexpr-конкатенацию array
В результате идентификация типов происходит в compile-time! Мелочь, но приятная
Идентификаторы затем можно сериализовывать, передавать между модулями, сравнивать и т.д.
Буду благодарен, если кто укажет на ошибки, потенциальные проблемы, предложит улучшения, альтернативы.
P.s.
Небольшие косметические улучшения:
Написал функцию MakeTypeId(1), чтобы вместо return array<int8_t,1>{1} писать MakeTypeId(1);
И написал более компактную функцию join, которую можно использовать для объединения не двух, а любого числа array:
N>Есть некий конечный набор пользовательских типов и задача их идентифицировать во время выполнения не используя RTTI.
N>Тип идентификатора не важен. Варианты без constexpr известны.
В качестве идентификатора типа берем std::array.
Для шаблонных типов делаем constexpr-конкатенацию array
// Реализацию функции join берем отсюда(спасибо автору Klemens Morgenstern): https://gist.github.com/klemens-morgenstern/b75599292667a4f53007
template<typename T, std::size_t L, std::size_t R>
constexpr std::array<T, L+R> join(std::array<T, L> rhs, std::array<T, R> lhs) {...};
struct IntCodec
{
static constexpr auto Id() { return array<int8_t,1>{1}; }
// ...
};
struct CharCodec
{
static constexpr auto Id() { return array<int8_t,1>{2}; }
// ...
};
template<typename T>
struct VectorCodec
{
static constexpr auto Id()
{
return join(array<int8_t,1>{3}, T::Id());
}
// ...
};
int main()
{
constexpr auto id1 = IntCodec::Id(); // 1
constexpr auto id1 = VectorCodec<CharCodec>::Id(); // 3,2
constexpr auto id2 = VectorCodec<VectorCodec<IntCodec>>::Id(); // 3,3,1
return 0;
}
В результате идентификация типов происходит в compile-time! Мелочь, но приятная
Идентификаторы затем можно сериализовывать, передавать между модулями, сравнивать и т.д.
Буду благодарен, если кто укажет на ошибки, потенциальные проблемы, предложит улучшения, альтернативы.
P.s.
Небольшие косметические улучшения:
Написал функцию MakeTypeId(1), чтобы вместо return array<int8_t,1>{1} писать MakeTypeId(1);
template <typename... Types>
constexpr auto MakeTypeId(Types&&... t)
{
return std::array<int8_t, sizeof...(Types)>{ std::forward<Types>(t)... };
}
И написал более компактную функцию join, которую можно использовать для объединения не двух, а любого числа array:
template<typename... TArrs>
constexpr auto join(const TArrs&... arrs)
{
std::size_t i = 0;
std::array<int8_t, (arrs.size() + ...)> ret{};
([&](const auto& arr)
{
for (const int8_t& val : arr)
ret[i++] = val;
}(arrs), ...);
return ret;
}