Научная статья на тему 'Концепты C++17 в их отношении к концептам C++0x'

Концепты C++17 в их отношении к концептам C++0x Текст научной статьи по специальности «Компьютерные и информационные науки»

CC BY
833
55
i Надоели баннеры? Вы всегда можете отключить рекламу.
Ключевые слова
ОБОБЩЁННОЕ ПРОГРАММИРОВАНИЕ / КОНЦЕПТЫ C++ / ШАБЛОНЫ C++ / КОНТРОЛЬ ТИПОВ

Аннотация научной статьи по компьютерным и информационным наукам, автор научной работы — Пеленицын Артем Михайлович

В статье проводится анализ текущего проекта концептов для C++ 2017 на основе выявления проблем концептов C++0x, которые планировалось включить в стандарт языка 2011 года. Показано, что неудача концептов C++0x напрямую повлияла на конкретные проектные решения, вошедшие в новый дизайн концептов.

i Надоели баннеры? Вы всегда можете отключить рекламу.
iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
i Надоели баннеры? Вы всегда можете отключить рекламу.

Текст научной работы на тему «Концепты C++17 в их отношении к концептам C++0x»

Пеленицын А.М.

Южный федеральный университет, Институт математики, механики и компьютерных наук им. И.И. Воровича, ассистент кафедры информатики и вычислительного эксперимента,

apel@sfedu.ru

КОНЦЕПТЫ C++17 В ИХ ОТНОШЕНИИ К КОНЦЕПТАМ C++0X

КЛЮЧЕВЫЕ СЛОВА

Обобщённое программирование, концепты C++, шаблоны C++, контроль типов АННОТАЦИЯ

В статье проводится анализ текущего проекта концептов для C++ 2017 на основе выявления проблем концептов C++0x, которые планировалось включить в стандарт языка 2011 года. Показано, что неудача концептов C++0x напрямую повлияла на конкретные проектные решения, вошедшие в новый дизайн концептов.

Неограниченный параметрический полиморфизм, как он представлен в механизме шаблонов C++98, имеет ряд известных недостатков, главным из которых является невозможность генерации разборчивых сообщений об ошибках. На протяжении 2000-х и 2010-х рассматриваются средства введения ограниченного параметрического полиморфизма в язык C++. Мы исследуем наиболее актуальное из таких предложений — способ определения и применения ограничений на параметры шаблонов C++, так называемые концепты C++1z (также: Concepts Lite), планируемые к включению в стандарт языка 2017 года.

Все рассмотренные нами источники по дизайну концептов C++1z имеют общий недостаток, а именно, в описании нового механизма практически не говорится о том, какие факторы повлияли на принятие конкретных проектных решений. На наш взгляд, важнейшие из этих решений продиктованы проблемами, возникшими в старом дизайне концептов C++0x. Анализ этой связи между двумя проектами позволяет лучше понять основные черты готовящихся изменений в языке C++. Именно этот анализ предлагается в нашей статье.

В рассмотрении проекта концептов C++1z мы используем ряд документов комитета по стандартизации C++: некоторые примеры взяты из неформального введения в тему [1]; детали синтаксиса уточнены по более свежему формальному документу-описанию изменений в текст стандарта языка [2]; изменения в стандартной библиотеке пока ещё не пересмотрены в свете последней редакции концептов, но некоторое представление о них можно получить по отчёту [3]. Мнение автора языка C++, Бьярне Страуструпа приводится в основном по статье [4].

Статья состоит из пяти частей. В первой части приводится пример, который должен иллюстрировать основную проблему неограниченных шаблонов C++98 и преимущества, которые предполагается получить после введения концептов в новый стандарт языка. Во второй части приводится краткий обзор старого проекта концептов C++0x и основные причины его неудачи — невключения в стандарт 2011 года. В третьей части описываются главные черты нового проекта концептов и их связь с проблемами старого проекта. В четвёртой части рассматривается один из важных элементов ограниченного параметрического полиморфизма: перегрузка на основе концептов, и то, как авторам нового проекта удалось реализовать её в условиях отсутствия явных моделей концептов. В пятой части даны замечания по текущему состоянию нового проекта — деталям синтаксиса и доступности его реализации.

1. Пример и мотивация

Одна из главных проблем шаблонов C++98 состоит в длинных ошибках компиляции. Происходят они от того, что несоответствие типа неявным требованиям выясняется посреди процесса подстановки этого типа в определение шаблона. В результате текст ошибки ссылается на детали реализации шаблона, которым не смог удовлетворить тип-аргумент. Однако клиент шаблона, как правило, ничего не знает о его реализации.

Типичный пример такого несоответствия можно составить с помощью распространённой ошибки, которая состоит в попытке отсортировать список общим алгоритмом. В стандартной библиотеке C++ общий алгоритм сортировки подразумевает произвольный доступ к элементам сортируемого контейнера, в то время как тип списка такой доступ не предоставляет. Приведём

пример заголовка шаблона функции сортировки, который несколько проще стандартного алгоритма и принимает не пару итераторов, а контейнер целиком — в трёх вариантах (в своей реализации такой шаблон может, к примеру, вызывать стандартный алгоритм std::sort)._

Листинг 1: Функция сортировки контейнера: неограниченный полиморфизм

template<typename Cont> void sort(Cont & c);

В листинге 1 ничто не указывает на предположения о типе-параметре кроме его имени — типичная ситуация для неограниченного полиморфизма.

Листинг 2: Функция сортировки контейнера: ограниченный полиморфизм, полная и сокращённая версии

template<typename Cont>

requires Sortable<Cont>() void sort(Cont & c);

template<Sortable Cont> void sort(Cont & c);

В листинге 2 приведены две эквивалентных версии в синтаксисе концептов, предлагаемом для C++17, причём вторая, сокращённая, совпадает также и с вариантом, предлагавшимся для концептов C++0x. В ней видно использование явного ограничения Sortable — это и есть именованный набор требований к шаблонному параметру Cont, который называется концептом. В данном случае набор требований должен обеспечивать произвольный доступ к элементам контейнера и наличие операции «меньше» для этих элементов.

Наиболее важным свойством концептов является то, что проверка соответствия аргумента заданным требованиям проводится до того, как начинается подстановка этого аргумента в тело шаблона. Таким образом, при возникновении несоответствий компилятор сообщит о них незамедлительно и в терминах ограничений, представленных в интерфейсе обобщённой компоненты, а не её реализации. Имеющиеся прототипы реализаций концептов C++0x и C++1z дают существенно более доступные сообщения об ошибках в подобных случаях, чем это было с неограниченными шаблонами C++98. Проиллюстрируем это на примере с сортировкой списка..

Сообщение об ошибке с вызовом стандартного алгоритма sort для стандартного списка в компиляторе GCC 4.9 занимает 67 строк, непосредственно текст ошибки плохо отражает существо проблемы, выглядит следующим образом:

no match for 'operator-' (operand types are 'std::_List_iterator<int>' and 'std::_ListJterator<int>') Ошибка сопровождается большим количеством «замечаний» (англ. note), которые должны помочь программисту понять причину ошибки, но на деле имеет малую ценность. Аналогичная ошибка с концептами C++1z занимает около 6 строк, и выглядит следующим образом: error: cannot call function 'void sort(const C&) [with C = std::__cxx11::list<int>]' note: constraints not satisfied void sort(C const & ) {}

A

note: concept 'Sortable<std::__cxx11::list<int, std::allocator<int> > >' was not satisfied В данном случае замечания совершенно точно отражают суть дела.

Концепты это новая сущность языка программирования, которая не укладывается в систему типов C++98. Это отличает механизм ограниченного параметрического полиморфизма, предлагаемый для C++, от ограниченного параметрического полиморфизма, основанного на подтипировании и характерного для чистых объектно-ориентированных языков, таких как Java и C#. (Отметим, что последний упомянутый подход неоднократно критиковался с предложением улучшений [5-7].) В связи с этим мы считаем важным всесторонний анализ дизайна концептов для C++ и предлагаем вариант такого анализа на основе сравнения текущего проекта концептов с проектом, предлагавшимся для включения в C++11. На наш взгляд основные черты нового проекта прямо вытекают из проблем, возникших в проекте концептов C++0x. 2. Концепты C++0x и их проблемы

Обсуждение концептов C++1z следует начать с анализа целей и причин неудачи концептов C++0x. Кратко перечислим основные элементы проекта концептов C++0x, которые одновременно являются достаточно общими требованиями к механизму ограниченного параметрического

полиморфизма.

1.Синтаксис для определения именованного набора ограничений — концепта.

2.Синтаксис для наложения ограничения (концепта) при объявлении шаблона класса или функции.

3.Способ проверки соответствия использования шаблонных параметров внутри шаблона класса или функции наложенным ограничениям.

4.Способ указания соответствия конкретных типов тем или иным концептам — так называемые модели концептов (concept map).

Оказалось, что основные сложности доставляли пункты 3 и 4. Первый из них требовал существенной модификации алгоритма поиска имён при обработке шаблонов компилятором. Такая модификация была выполнена в рамках проекта ConceptGCC [8], работала она весьма медленно и нестабильно. Мнение разработчиков этой версии состоит в том, что при необходимой доработке, проблем с производительностью компилятора быть не должно. Однако сам масштаб изменений, которые требовалось внести в распространённые компиляторы в отношении обработки шаблонов, негативно воспринимался членами комитета по стандартизации.

Второй проблемный пункт (4-й в списке выше) с моделями концептов неоднозначно воспринимался даже основным идеологом концептов C++0x, автором языка C++ Бьярне Страуструпом. Дело в том, что свидетельства соответствия конкретных типов некоторым концептов во многих случаях тривиальны и могут быть автоматически установлены компилятором. Однако такой автоматизм может плохо сочетаться с другими возможностями обновлённых шаблонов, как например, перегрузкой на основе концептов. Более того, в комитете по стандартизации высказывались мнения, что получение моделей концептов без участия, а значит, без явного намерения программиста просто неверно идеологически.

В целом, по состоянию на 2009 год проект концептов C++0x оценивался Б. Страуструпом как переусложнённый, рассчитанный на программистов-экспертов, в то время как изначальная идея состояла в создании механизма, облегчающего жизнь «среднему» программисту. Автор языка C++ предложил пять радикальных шагов по упрощению концептов, однако комитет по стандартизации не видел возможности обсуждать дополнительные предложения до принятия нового стандарта: сроки для внесения изменений подходили к концу. В итоге концепты были оставлены для будущих редакций стандарта языка.

3. Концепты C++1z в их отношении к концептам C++0x

Проект концептов для стандарта 2017 года был создан с нуля, но в соответствии с опытом, полученным при разработке концептов C++0x. Основные задачи, стоявшие перед авторами нового проекта, можно сформулировать следующим образом.

• Простота и понятность для «среднего» программиста.

•Отказ (возможно, временный) от средств, породивших наибольшие споры при обсуждении концептов C++0x.

•Учёт объективной сложности адаптации промышленных компиляторов.

•Обратная совместимость со стандартом языка 1998 года, в том числе, с неограниченными шаблонами (как и у концептов C++0x).

В этом разделе мы укажем две черты концептов C++1z, который вытекают из этих целей и отличают их от концептов C++0x: они связаны в первую очередь с двумя проблемными пунктами списка, приведённого в прошлом разделе. В следующих двух разделах обсуждаются другие черты концептов C++1z, важные с точки зрения обобщённого программирования.

Отсутствие контроля типов внутри шаблонов — возможно, самая неожиданная черта концептов C++1z, если смотреть на них без учёта изложенной выше предыстории. Контроль типов внутри шаблонов представлял потенциально особую сложность для адаптации промышленных компиляторов, как упоминалось в предыдущем разделе. Связано это, в частности, с тем, что новые ограниченные шаблоны должны были успешно сосуществовать и взаимодействовать со старыми, неограниченными шаблонами C++98. Если, к примеру, из шаблона первого типа вызывался шаблон второго, то проконтролировать корректность требований внешнего шаблона было достаточно сложно: фактически, задача свелась бы, как и прежде, поиску ошибок путём подстановки шаблонных аргументов. Обработка подобных сочетаний существенно усложняла комиплятор, не принося никакого выигрыша по сравнению со старым подходом стандарта 1998 года.

Таким образом, в концептах C++1z было решено полностью исключить проверку соответствия требований, наложенных в заголовке шаблона, и определения этого шаблона. То

есть проверяется лишь соответствие аргументов шаблона в месте его использования, в то время как в теле шаблона параметры обрабатываются компилятором так же, как это было с шаблонами C++98. Данный подход считается разумным компромиссом в связи с тем, что автор обобщённой компоненты зачастую более квалифицированный специалист, чем её пользователь: он должен сформулировать набор ограничений к аргументам своей компоненты и написать её определение так, чтобы оно соответствовало этим требованиям, не рассчитывая на помощь компилятора в этой задаче. Далее, многочисленные использования однажды написанной компоненты будут уже проверяться именно компилятором.

Этим изменением объясняется различие двух проектов концептов с точки зрения модулярного контроля типов. Модулярный контроль типов означает, что если определение обобщённой компоненты было однажды принято компилятором, то при любой подстановке аргументов, удовлетворяющих ограничениям, повторная проверка определения не требуется. В концептах C++0x это условие удовлетворялось лишь частично по причине возможного использования неограниченных шаблонов внутри ограниченных. В концептах C++1z вначале проверяется соответствие аргументов требованиям, однако во время подстановки могут произойти ошибки в том случае, если автор шаблона неточно описал эти требования.

Полностью автоматическая проверка соответствия типов наложенным ограничениям или отказ от моделей концептов — вторая важная черта, отличающая концепты C++1z. Как упоминалось в прошлом разделе, механизм моделей концептов вызывал много вопросов, связанных с запретом или разрешением генерации таких моделей. В проекте для C++1z было решено максимально упростить использование концептов с помощью удаления самого понятия моделей концептов.

Таким образом, если тип не может быть однозначно и автоматически отображён на нужный набор требований, то он будет отвергнут компилятором. Имеющийся способ решения этой проблемы — модифицировать рассматриваемый тип нужным образом, зачастую не представляет трудностей, но разрушает совместимость с кодом, который уже использует старое определение данного типа. Эта проблема непосредственно связана с одним из важных свойств обобщённого программирования, известным как ретроактивное моделирование. Ретроактивное моделирование предполагает возможность определения того, каким образом тип удовлетворяет концепту, без изменения типа. С удалением моделей концептов говорить о поддержке этого свойства если и можно, то только в очень ограниченном объёме, а именно: всегда можно добавлять перегруженные версии свободных функций, работающих с объектами данного типа. Однако наличие свободных функций является лишь одним из нескольких типов требований, которые могут накладывать концепты.

Завершая сравнение концептов C++0x и концептов C++1y, отметим, что в последних по сравнению с первыми были исключены также:

•аксиомы — средство описания семантических ограничений,

•синтаксическая поддержка уточнения (refinement) или, попросту, «наследования» концептов.

Аксиомы это достаточно высокоуровневые правила, которые в общем случае невозможно проверить с помощью компилятора. Пример аксиомы приведён в листинге 3: здесь показано, что полугруппой является пара из типа T и бинарной операции над элементами этого типа, причём операция должна быть ассоциативной — это условие сформулировано в виде аксиомы.

Аксиомы предполагались в помощь компилятору для проведения оптимизирующих преобразований. Соответствующие исследования проводились несколькими исследователями, поддерживавшими эту идею, однако число их было слишком мало, чтобы обеспечить вхождение механизма с таким нечётким назначением в новый упрощённый проект концептов.

Листинг 3: Аксиома ассоциативности — часть определения концепта полугруппы

concept Semigroup<typename Op, typename T> : CopyConstructible<T> { T operator()(Op, T, T); axiom Associativity(Op op, T x, T y, T z) { op(x, op(y, z)) == op(op(x, y), z);

}

}

Пример уточнения также приведён на листинге 3: тип T в концепте полугруппы должен иметь конструктор копий (CopyConstructible<T>). Как замечено Дугом Грегором, одним из авторов концептов C++0x, в предложении по их упрощению [11], в отсутствии моделей концептов уточнения полностью эквивалентно ограничениям, которые можно накладывать на тип внутри определения концепта.

4. Перегрузка на основе концептов и связанная с ней проблема

В связи с удалением из нового дизайна концептов явных моделей возникает следующая проблема.

В техническом отчёте 2005 года ведущие специалисты в области обобщённого программирования, Дуг Грегор и Джереми Сик, высказали идею о том, что для успешной реализации перегрузки на основе концептов необходимо наличие механизма явного сопоставления концепта и типа, который должен ему удовлетворять. Пример Грегора и Сика достаточно прост и интересен, чтобы его рассмотреть и понять, как решают возникающую в нём проблему авторы концептов C++1z. Отметим сразу, что хотя упомянутое решение можно найти в описании проекта изменений в стандартную библиотеку в связи с запланированным добавлением концептов C++1z, само описание изменений библиотеки весьма обширно, а авторы новых концептов не вынесли это важное, по нашему мнению, решение ни в одну из известных нам статей или докладов, посвящённых новому элементу языка.

Пример, по существу, ставит проблему концептов, которые различаются только семантически. В качестве примера таких концептов можно взять широко распространённые в стандартной библиотеке C++ категории итераторов, которые планируется конвертировать в концепты в будущем стандарте. Хорошо известно, что итераторы ввода и прямые итераторы

отличаются лишь семантикой операции инкремента._

Листинг 4: Перегрузка на основе концептов: конструктор типа vector с разной эффективностью

// O(lg n) allocations template<Input_iterator Iter>

vector(Iter first, Iter last) {

while (first != last) push_back(*first++);

}

// 1 allocation

template<Forward_iterator Iter>

vector(Iter first, Iter last) {

auto n = distance(first, last);

reserve(n);

while (n--) push_back(*first++); }_

В листинге 4 приведён пример перегрузки функций-членов, а именно, конструкторов типа vector, принимающих итераторы начала и конца диапазона, элементы которого надо загрузить в создаваемый вектор. Перегрузка осуществляется на основе категории итератора, который задаётся концептом: для итератора ввода необходимо многократно выделять (O(lgn) выделений, если расширение происходит с помощью кратного увеличения резерва памяти), в то время как прямой итератор позволяет заранее вычислить количество элементов в полученном диапазоне и обойтись одним выделением.

Проблема состоит в том, что, как отмечалось, выше любой тип, (синтаксически) входящий в категорию итератора ввода, будет принадлежать также и категории прямого итератора. Как показал анализ предложения по редактированию стандартной библиотеки в связи с планируемым добавлением концептов, семантическое различие между разными типами авторы планируют, как и в старом стандарте кодировать заранее определёнными типами-метками (tag), для которых внутри типов-итераторов задаётся стандартный псевдоним iterator_category. На листинге 5 показано, как примерно должен выглядеть при таком подходе концепт итератора ввода.

Из листинга 5 видно, что данный концепт уточняет (refines) концепт WeakInputIterator, который включает некоторые элементарные свойства итераторов, такие как наличие операций разыменования и продвижения. Ограничения на тип-параметр I состоят в том, что объекты этого

типа должны быть сравнимы на равенство (EquaHtyComparaЫe) и должны содержать вложенный синоним типа под названием iterator_category (его значение возвращает выражение IteratorCategory<I>), который наследуется (в частности, как часто бывает, равен) от стандартного типа-метки input_iterator_tag._

Листинг 5: Концепт итератора ввода

template<typename I> concept bool Inputlterator = WeakInputIterator<I>() && EqualityComparable<I>() && Derived<IteratorCategory<I>, input_iterator_tag>(); Заметим, что строгое равенство типов обеспечивается аналогичным Derived отношением Same. Оба они вычисляются с помощью средств заголовочного файла type_traits стандартной библиотеки, появившегося в C++11, и, таким образом, не требуют существенной модификации существующих компиляторов.

5. Заключительные замечания относительно синтаксиса и реализации концептов C+

+1z

В предыдущих разделах мы не останавливались на специальном обсуждении синтаксиса для концептов, отдавая основное внимание семантике. Синтаксис концептов продолжает меняться и любые конкретные определения здесь могут быстро устареть. Однако для понимания языка описания концептов (пункт 1 из списка в разделе 2) следует сделать общее замечание относительно идеи введения новых синтаксический конструкций в язык программирования. Идея эта в целом заключалась в том, чтобы максимально использовать новые возможности из последних стандартов языка: 2011 и 2014 года.

Ключевое слово concept может появляться в одном из двух контекстов:

• в определении шаблона constexpr-функции (появились в C++11) — такой пример даётся в листинге 6,

• в определении шаблона переменной (появились в C++14) — такой пример приводится в листинге 5.

Листинг 6: Концепт Аллокатора (менеджера памяти)

template<typename A>

concept bool AllocatorO {

return requires () { typename A::pointer; // (1)

requires Pointer<typename A::pointer>; // (2) // ...

};

}_

В обоих случаях это означает наложение некоторых ограничений на соответствующий шаблон функции или переменной. К примеру:

• тип возвращаемого значения шаблона функции, как и тип шаблона переменной должен быть логическим типом;

• у шаблона функции не должно быть параметров;

• в теле функции должен быть только оператор return, аргументом которого выступает логическое выражение, вычисляемое на этапе компиляции, возможно, включающее requires-подвыражение;

• и т. п.

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

Наиболее существенное добавление к синтаксису C++ происходит в связи с requires-выражением, оно может включать два вида предложений: обращение к вложенным типам (таким образом требуется их существование) или допустимые выражения. Пример второго вида требований приведён на листинге 7: requires позволяет вводить псевдопеременные параметра-типа T (в этом примере их имена a и b) и требовать, чтобы выражения сравнения на равенство и на неравенство были допустимыми для этих переменных и возвращали тип bool.

template<typename T>

concept bool Equality_comparable() {

return requires (T a, T b) { {a == b} -> bool; {a != b} -> bool;

};

}_

Приведённый синтаксис имеет ряд очевидных мелких недостатков. Например, указание типа bool в обоих видах концептов является избыточным. Кроме того: для использования концепта, определённого как функция, требуется указание круглых скобок (операции вызова функции), в то время как для переменной они не нужны и приведут к ошибке компиляции, если их добавить — это создаёт ненужное синтаксическое различие между разными концептами в то время как семантически они абсолютно эквиваленты.

Вполне возможно, что указанные недостатки будут сняты в будущих редакциях проекта нового стандарта [12].

В августе 2015 года прототипная реализация концептов на основе компилятора GCC была добавлена в основную ветвь разработки этого компилятора [13]. Это изменение планируется зафиксировать в версии 6 компилятора, которая запланирована к выходу весной 2016 года. Однако уже сейчас можно самостоятельно собрать данную версию компилятора из исходных кодов либо воспользоваться онлайн-ресурсами, предоставляющими веб-интерфейс к такой сборке [14]. Для включения механизма концептов при компиляции программ следует указывать ключ -std=C++1z.

Литература

1. Sutton A., Stroustrup B., Dos Reis G. Concepts Lite: тех. отч. — 28 июня 2013. — ISO/IEC JTC1/SC22/WG21 N3701.URL: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3701.pdf

2. Sutton A. C++ Extensions for Concepts PDTS: тех. отч. — 9 февр. 2015. — ISO/IEC JTC1/SC22/WG21 N4377.URL: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4377.pdf

3. A Concept Design for the STL: тех. отч. — 13 янв. 2012. — ISO/IEC JTC1/SC22/WG21 N3351. URL: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3351.pdf

4. Stroustrup B. The C++0x "Remove Concepts" Decision // Dr. Dobb's Journal. — 2009.URL: http://www.drdobbs.com/cpp/the-c0x-remove-concepts-decision/218600111

5. Jarvi J., Willcock J., Lumsdaine A. Associated types and constraint propagation for mainstream object-oriented generics // OOPSLA '05: Proceedings of the 20th annual ACM SIGPLAN conference on Object- oriented programming systems languages and applications. — ACM Press. New York, NY, USA : ACM Press, 2005. — С. 1-19. — ISBN 1-59593-031-0. — DOI: 10.1145/1094811.1094813.

6. Belyakova J., Mikhalkovich S. Pitfalls of C# Generics and Their Solution Using Concepts // Proceedings of the Institute for System Programming. — Moscow, Russia, 2015. — Июнь. — Т. 27, No 3. — С. 29-45. — ISSN 2079-8156.

7. Lightweight, flexible object-oriented generics / Y. Zhang [и др.] // 36th ACM SIGPLAN Conf. on Programming Language Design and Implementation (PLDI). — Июнь 2015. — С. 436-445. URL: http://www.cs.cornell.edu/andru/papers/genus

8. ConceptGCC. — URL: http://www.generic-programming.org/software/ ConceptGCC/

9. Concepts: Linguistic Support for Generic Programming in C++ / D. Gregor [и др.] // SIGPLAN Not. — New York, NY, USA, 2006. — Окт. — Т. 41, No 10. — С. 291-310. — ISSN 0362-1340. — DOI: 10.1145/1167515.1167499.

10. Tang X., Jarvi J. Axioms as generic rewrite rules in C++ with concepts / / Science of Computer Programming. — 2015. — Т. 97, Part 3. — С. 320-330. — ISSN 0167-6423. — DOI: 10.1016/j.scico.2014.05.006. — Object-Oriented Programming and Systems (OOPS 2010)Modeling and Analysis of Compositional Software (papers from EUROMICRO SEAA'12).

11. Gregor D. Simplifying C++0x Concepts: тех. отч. — 9 апр. 2013. — ISO/IEC JTC1/SC22/WG21 N3629. URL: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3629.pdf

12. Brown W. Tweaks to Streamline Concepts Lite Syntax: тех. отч. — 10 апр. 2015. — ISO/IEC JTC1/SC22/WG21 N4434. URL: http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4434.pdf

13. Merrill J. Huge C++ PATCH to merge c++-concepts branch — Mail archive for the GCC project. URL: https://gcc.gnu.org/ml/gcc-patches/2015-08/msg00377.html

14. Wandbox: Social Compilation Service. — URL: http://melpon.org/wandbox

i Надоели баннеры? Вы всегда можете отключить рекламу.