Концепции C ++: Как использовать «концепт» для проверки свойства шаблонной структуры? - PullRequest
3 голосов
/ 24 февраля 2020

Я сейчас экспериментирую с новой функцией "концепций" в c ++ 2a. Цель моего кода ниже - проверить некоторые свойства шаблонной структуры. Поскольку первый аргумент шаблона зарезервирован для проверяемого типа , у меня возникают трудности с использованием концепции без выражения requires или заданием аргументов шаблона вручную. Это не имеет большого значения, но мне нравится обозначение concept для ясности. Есть ли способ обойти это?

Компилятор

gcc-g++-10.0 (GCC) 10.0.1 20200119 (experimental)
Copyright (C) 2020 Free Software Foundation, Inc.

Команда компиляции

g++-10.0 -std=c++2a file.cc

Код


#include <concepts>

/// Struct has template arguments and a property that can be checked in a concept.
template <bool a> struct A {
  constexpr static bool property() noexcept { return a; }
};

template <typename T, bool a> concept hasProp = std::is_same_v<T, A<a>> && A<a>::property();

template <bool a> requires hasProp<A<a>, a> void works(A<a> c) {} 
template <bool a, hasProp<a> c> void deductionError(c d) {};

// This is a sketch of what I'd like to do:
// template <A<a, b> Class, bool a, bool b> concept hasProp = Class::property;

int main() {
  A<true> a;
  A<false> b;

  works(a);
  //works(b); //doesn't compile as the constraint is not fulfilled, which is desired.

  //deductionError(a); // I get why this deduction error occurs, but is it possible to do this
                      // in a clean way using concepts without having so specify template arguments?
}

Ответы [ 2 ]

2 голосов
/ 24 февраля 2020

Вам действительно нужен t ie -in для A?

template <typename T> concept hasProp = T::property();

template <bool a> requires hasProp<A<a>> void works(A<a>); // ok
template <hasProp C> void deductionError(C);               // also ok

Если вам нужен t ie -in, вы можете добавить это полностью локально к hasProp :

// unfortunately this is hard to generalize due to the non-type template parameter
template <typename T> struct is_A : std::false_type { };
template <bool b> struct is_A<A<b>> : std::true_type { };

template <typename T> concept hasProp = is_A<T>::value && T::property();

// ... and the rest works as before
template <bool a> requires hasProp<A<a>> void works(A<a>); // ok
template <hasProp C> void deductionError(C);               // also ok

В любом случае, hasProp должен просто взять тип.

2 голосов
/ 24 февраля 2020

Частичная специализация шаблона класса для спасения:

template<class T> 
struct HasProp : std::false_type{};

template<bool a>
struct HasProp<A<a>> : std::integral_constant<bool, A<a>::property()>
{};

template <class T> 
concept hasProp = HasProp<T>::value;

template <bool a> 
requires hasProp<A<a>>
void works(A<a>) {}

template<hasProp C> 
void deductionError(C){} // no longer a deductionError

Демо


Это (возможно, излишне) т ie ваша концепция A напрямую.

Вместо этого вы могли бы сделать это (Как @ Барри ответил ):

template <class T> 
concept hasProp = T::property();

Демо2

...