воскресенье, 13 марта 2016 г.

Концепты для бедных 2: require

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

В Concepts Lite TS для описания требований, налагаемых концептом, зарезервированно ключевое слово requires. За неимением оного в современных компиляторах, мы попробуем добиться как можно более похожего поведения с помощью шаблонного типа который назовём require (отличаемся в одну букву, чтобы не ломать компиляцию после появления концептов в C++). А реализацию этого шаблона можно безбожно стырить, опять же, из семнадцатых плюсов, где в стандартной библиотеке появится тип void_t. Прочитав его описание несложно понять как описать концепт Wriable требующий наличия перегрузки оператора вставки в поток:

template<typename T, typename = require<>>
struct is_writable: public std::false_type {};

template<typename T>
struct is_writable<T, require<
  decltype(std::declval<std::ostream&>() << std::declval<T>())
>>: public std::true_type {};

template<typename T>
using Writable = std::enable_if<is_writable<T>::value, T>::type

Где require это:

template<typename... T>
struct make_void {typedef void type;};

template<typename... T>
using require = typename make_void<T...>::type;

Комментариев нет: