Что-то вроде `declval` для понятий - PullRequest
0 голосов
/ 02 декабря 2018

Когда вы работаете с шаблонами и с decltype, вам часто требуется экземпляр определенного типа, даже если у вас его нет.В этом случае std::declval<T>() невероятно полезен.Это создает воображаемый экземпляр типа T.

Есть ли что-то похожее для понятий?то есть функция, которая создала бы и воображаемый тип для концепции.

Позвольте мне привести вам пример (немного надуманный, но должен служить цели):

Давайте определим концепцию Incrementable

template <typename T>
concept Incrementable = requires(T t){
   { ++t } -> T;                       
};

Теперь я хотел бы иметь концепцию, которая проверяет, есть ли у объекта оператор operator(), который может принять Incrementable.В моем воображаемом синтаксисе я написал бы что-то вроде этого:

template <typename F, typename T = declval<Incrementable>>
concept OperatesOnIncrementable = requires(F f, T t){
   { f(t) } -> T;
} 

Там declval в typename T = declval<Incrementable> создаст воображаемый тип T, который на самом деле не является конкретным типом, но для всех целей и задачведет себя как тип, который удовлетворяет Incrementable.

Есть ли механизм в следующем стандарте, чтобы учесть это?Я нашел бы это невероятно полезным.


Редактировать: Некоторое время назад я задал аналогичный вопрос , можно ли это сделать с boost::hana.


Редактировать: Почему это полезно?Например, если вы хотите написать функцию, которая составляет две функции

template <typename F, typename G>
auto compose(F f, G g) {
  return [f, g](Incrementable auto x) { return f(g(x)); };
}

Я хочу получить ошибку, когда пытаюсь составить две функции, которые не могут быть скомпонованы.Не ограничивая типы F и G, я получаю ошибку только при попытке вызвать составную функцию.

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Есть ли что-то похожее для понятий?то есть функция, которая создала бы и воображаемый тип для понятия.

Термин для этого - архетип .Создание архетипов было бы очень ценной функцией и очень важно для таких вещей, как проверка определений.Из ответа ТК:

Таким образом, даже если бы вы могли волшебным образом синтезировать какой-то уникальный тип, вы все равно не можете гарантировать, что F работает на всех Incrementable типах.

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

Придумать правильный архетип невероятно сложно.Например, для

template <typename T>
concept Incrementable = requires(T t){
   { ++t } -> T;                       
};

Соблазнительно написать:

struct Incrementable_archetype {
    Incrementable_archetype operator++();
};

Но это не "как можно меньше" - этот тип является конструируемым и копируемым по умолчанию (не требования, которыеIncrementable накладывает), и его operator++ возвращает точно T, что также не является обязательным требованием.Таким образом, действительно хардкорный архетип будет выглядеть так:

struct X {
    X() = delete;
    X(X const&) = delete;
    X& operator=(X const&) = delete;

    template <typename T> operator,(T&&) = delete;

    struct Y {
        operator X() &&;
    };
    Y operator++();
};

Если ваша функция работает для X, то, вероятно, она работает для всех Incrementable типов.Если ваша функция не работает для X, то вам, вероятно, нужно либо изменить реализацию, чтобы она работала, либо изменить ограничения, чтобы предоставить больше функциональности.

Для получения дополнительной информации ознакомьтесь с BoostConcept Check Library , которая довольно старая, но очень интересная, по крайней мере, для прочтения документации.

0 голосов
/ 02 декабря 2018

Не существует такого механизма.

Также это не представляется реализуемым / полезным, поскольку существует неограниченное количество типов Incrementable, и F может отклонить подмножество, выбранное с использованием произвольно сложногометапрограмма.Таким образом, даже если бы вы могли волшебным образом синтезировать какой-то уникальный тип, вы все равно не можете гарантировать, что F работает на всех Incrementable типах.

...