Поддерживает ли C++11 рекурсию типов в шаблонах?

Хочу подробно объяснить вопрос. Во многих языках со строгой системой типов (, таких как Felix, Ocaml, Haskell ), вы можете определить полиморфный список, составив конструкторы типов. Вот определение Felix:

typedef list[T] = 1 + T * list[T];
typedef list[T] = (1 + T * self) as self;

В Ocaml:

type 'a list = Empty | Cons ('a, 'a list)

В C это рекурсивно, но не полиморфно и не композиционно:

struct int_list { int elt; struct int_list *next; };

В C++ это было бы сделано так, если бы C++ поддерживал рекурсию типов:

struct unit {};
template<typename T>
    using list<T> = variant< unit, tuple<T, list<T>> >;

при наличии подходящего определения для кортежа (также известная как пара )и вариант (, но не сломанный, используемый в Boost ). В качестве альтернативы:

    using list<T> = variant< unit, tuple<T, &list<T>> >;

может быть приемлемым, учитывая несколько иное определение варианта.Невозможно было написать это даже на C++ < C++11, потому что без шаблонных определений типов невозможно получить полиморфизм, а без нормального синтаксиса для определения типов невозможно получить целевой тип в области видимости. Приведенный выше синтаксис using решает обе эти проблемы, однако это не означает, что рекурсия разрешена.

В частности, обратите внимание, что разрешение рекурсии сильно влияет на ABI, то есть на изменение имени (это невозможно сделать, если схема изменения имени не допускает представления фиксированных точек ).

Мой вопрос :необходим для работы на C++11? [Предполагая, что расширение не приводит к бесконечно большой структуре]


Изменить :просто для ясности, требуется общая структурная типизация. Шаблоны предусматривают именно то, что, например

pair<int, double>
pair<int, pair <long, double> >

анонимно (структурно )типизированы, а пара явно полиморфна. Однако рекурсия в C++ < C++11 не может быть указана даже с помощью указателя. В С++ 11 вы можете указать рекурсию, хотя с шаблоном typedef (с новым синтаксисом using выражение в левой части знака = находится в области действия в правой части ).

Структурная (анонимная )типизация с полиморфизмом и рекурсией являются минимальными требованиями к системе типов.

Любая современная система типов должна поддерживать функторы полиномиальных типов, в противном случае система типов слишком громоздка для любого вида программирования высокого уровня. Комбинаторы, необходимые для этого, обычно указываются теоретиками типов, такими как :

1 | * | + | fix

, где 1 — единичный тип, *— формирование кортежа, + — формирование варианта, а fix — рекурсия. Идея состоит в том, что:

если t является типом и u является типом, то t + u и t *u также являются типами

В C++ struct unit{} равно 1, tuple равно *, Вариант равен +, и точки фиксации могут быть получены с использованием синтаксиса =. Это не совсем анонимная типизация, потому что для fixpoint потребуется определение типа шаблона.


Изменить :Просто пример конструктора полиморфных типов в C:

T*          // pointer formation
T (*)(U)    // one argument function type
T[2]        // array

К сожалению, в C значения функций не являются композиционными, и формирование указателя зависит от ограничения lvalue, а синтаксические правила для композиции типов сами по себе не являются композиционными, но здесь мы можем сказать :

if T is a type T* is a type
if T and U are types, T (*)(U) is a type
if T is a type T[2] is a type

, чтобы эти конструкторы типов (комбинаторы )можно было применять рекурсивно для получения новых типов без необходимости создавать новый промежуточный тип. В C++ мы можем легко исправить синтаксическую проблему :

template<typename T> using ptr<T> = T*;
template<typename T, typename U> using fun<T,U> = T (*)(U);
template<typename T> using arr2<T> = T[2];

, так что теперь вы можете писать :

arr2<fun<double, ptr<int>>>

, а синтаксис композиционный, как и типизация.

5
задан Yttrill 25 April 2012 в 20:07
поделиться