Есть ли способ сделать переменную типа в C ++? - PullRequest
0 голосов
/ 12 октября 2019

Мне интересно, как создать переменную типа. Что я имею в виду под этим, объясняется в коде ниже:

using var = type_var<int>; // currently var is of type type_var<int>

/// somewhere like in constexpr functions
var::store<float>;         // now var is of type type_var<float>
static_assert(std::is_same<var::get_type, float>::value, "");

Конечно, насколько мне известно, этот код никогда не будет работать, так как using сделает var «неизменяемым».

Но все же, мне интересно, есть ли способ хранения типов изменчиво.

1 Ответ

0 голосов
/ 12 октября 2019

В этом вопросе я спрашиваю: есть ли способ сделать элемент, который хранит тип, тип которого может содержаться в элементе во время компиляции.

простой ответ - нет!

В языке программирования 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.

...