В этом вопросе я спрашиваю: есть ли способ сделать элемент, который хранит тип, тип которого может содержаться в элементе во время компиляции.
простой ответ - нет!
В языке программирования c ++ не было чего-то вроде «переменных времени компиляции». Все и все следуют Единому правилу определения (ODR)
C ++ предлагает с шаблонами собственный тип языка времени компиляции, часто называемый Шаблон метапрограммирования (TMP) В языке TMP используется общая концепция функционального языка программирования .
Взятый из приведенного выше связанного текста:
Функциональные программы не имеют операторов присваивания, то есть значение переменной в функциональной программе никогда не изменяется после определения.
Если я понимаю ваш псевдо-пример кода, вы думаете что-то вроде следующего:
template < auto x >
struct Variable
{
static constexpr decltype(x) value = x;
};
Variable< 10 > intvar;
Variable< 'a' > charvar;
int main()
{
// accessing the data:
std::cout << intvar.value << std::endl;
std::cout << charvar.value << std::endl;
}
Но в мире шаблонов и типов у вас нет шансов «присвоить» новое значение, нивведите в шаблон больше, просто не имея никакого синтаксиса для него.
Вы также можете программировать алгоритмы в TMP, но все «результаты» «вызовов» не находятся ни в какой переменной, они всегдаопределить новые "значения".
Пример некоторых шаблонов метапрограммирования. В примере показано, как написать «добавить» «функцию». Это добавит контейнеры двух типов ...
// define a data structure which can contain a list of types
template < typename ... TYPES >
struct TypeContainer;
// let us define some TMP "variables", which are types in c++
using list1 = TypeContainer<int, float, int >;
using list2 = TypeContainer< char, bool, int >;
// and now we define a TMP "function"
template < typename ... PARMS > struct Concat;
// which simply adds two typelists
template < typename ... LIST1, typename ... LIST2 >
struct Concat< TypeContainer< LIST1... >, TypeContainer< LIST2...>>
{
using RESULT = TypeContainer< LIST1..., LIST2...>;
};
using list3 = Concat<list1, list2 >::RESULT;
// But you never can change the "variable", because of the
// One Definition Rule (ODR)
// ( will fail to compile )
//using list2 = Concat<list1, list2 >::RESULT;
// helper to let us know what we have in the typelists:
// works for gcc or clang but is implementation specific
template < typename T>
void Print()
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
int main()
{
Print<list3>();
}
Вы найдете такие алгоритмы, уже определенные в STL. Там у вас есть std :: tuple в качестве контейнера типов и std :: tuple_cat для "добавления" двух кортежей. Мой код должен дать вам простой пример, чтобы понять, что мы делаем, не совершая каких-то волшебных вещей внутри STL.