Реализация концепций в C ++ 17 - PullRequest
0 голосов
/ 31 января 2019

Я видел выступление Бьярна Страуструпа под названием «Концепции будущего универсального программирования», и я подумал, может быть, я смогу написать «Концепции» на C ++ 17 ... Но я программист на C, с которого я началC ++ около 6 месяцев назад ... так что я не знаю почему, но у меня возникли проблемы с этим кодом.Кто-нибудь может мне помочь?

Я реализовал концепцию Addable с помощью короткого кода tmp ... Идея в том, что в C ++ 20 будет что-то вроде этого:

  template<typename T>
  concept Summable = requires(T x) { x + x; };

  template<typename T> requires Summable<T>
  T sum(T n1, T n2) {
     return n1 + n2;
  }

И этот код - это то, что на самом деле есть в C ++ 17:

 template <typename, typename, typename = void>
 struct Addable : std::false_type {};

 template <typename T, typename U>
 struct Addable < T, U,
                 std::void_t<decltype(std::declval<T&>()+std::declval<U&>())> > 
             : std::true_type {};

Код вершины компилируется и работает, но когда я пишу, следующий код не компилируется ...

 template<typename Head, typename ... Tail>
 auto sum(Head h, Tail ... args) {
    static_assert(Addable<Head, Tail...>::value, "Requires addable objects");
    return h+(args+...);
 }

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Вы можете изменить свое утверждение на

template <typename Head, typename ... Tail>
auto sum(Head h, Tail ... args) {
    static_assert((Addable<Head, Tail>::value || ...), "Requires addable objects");
    return (h + ... + args);
}

, поскольку ваши черты работают только для 2 типов.

Обратите внимание, что SFINAE больше похож на концепцию , чем static_assert.

0 голосов
/ 01 февраля 2019

Ваш код работает , если вы предоставляете только два аргумента для sum.

Проблема в том, что когда вы вызываете что-то вроде sum(1, 2, 3), Addable<Head, Tail...> становится Addable<int, int, int>, что не соответствует вашей частичной специализации Addable<T, U, void>.Если вы вызываете sum с более чем тремя аргументами, то шаблон Addable, который соответствует вообще, отсутствует, поскольку Addable принимает только три параметра шаблона.

Если вы хотите иметь возможность работать с более чемдва аргумента, вам понадобится другой подход.Это то, что я придумал.Он использует подход, аналогичный тому, который вы использовали, только с дополнительным косвенным указанием уровня для поддержки более двух аргументов:

template <typename T, typename U, typename = void>
struct Helper : std::false_type {};

template <typename T, typename U>
struct Helper<T, U, std::void_t<decltype(std::declval<T>() + std::declval<U>())>> : std::true_type {};

template <typename, typename...>
struct Addable : std::false_type {};

template <typename T, typename U, typename... V>
struct Addable<T, U, V...> : std::conditional_t<Addable<T, U>::value,
                                                Addable<U, V...>,
                                                std::false_type> {};

template <typename T, typename U>
struct Addable<T, U> : Helper<T, U> {};

template<typename Head, typename ... Tail>
auto sum(Head h, Tail ... args) {
    static_assert(Addable<Head, Tail...>::value, "Requires addable objects");
    return h+(args+...);
}

Live Demo

...