概念是否需要 constexpr 值或函数?

Can a concept require a constexpr value or function?

所以,我想做一些高级的类型级黑客,为此我真的很希望能够编写一个概念,要求类型具有与之关联的 constexpr int 值,这我稍后可以在与整数 std::array 模板参数相同的概念中使用。

可以写

template<typename T>
concept bool HasCount = requires {
    typename T::count;
};

但这不是我想要的;我希望 T::count 成为 static constexpr int。但是,代码(甚至不包括所需的constexpr

template<typename T>
concept bool HasCount = requires {
    int T::count;
};

不能在 GCC 7.3.0 上用 "error: expected primary-expression before 'int'" 编译。

另一个失败的尝试:可以写这个,这需要static int T::count():

template<typename T>
concept bool HasCount = requires {
    {T::count()} -> int;
};

但不是这个,这就是我想要的:

template<typename T>
concept bool HasCount = requires {
    {T::count()} -> constexpr int;
    {T::count() constexpr} -> int; // or this
    {constexpr T::count()} -> int; // or this (please forgive me for fuzzing GCC instead of reading the manual, unlike perl C++ is not an empirical science)
};

所以,我想知道是否有可能以任何方式要求概念表达式是 constexpr 限定的,或者如果不是,是否有不可能的原因,或者如果它不是包含在规范中。

理论上,这可以通过要求 T::count 是一个有效的表达式,并要求在需要常量表达式的上下文中使用 T::count 是有效的。例如:

#include <type_traits>
#include <utility>

template<int> using helper = void;

template<typename T>
concept bool HasCount = requires {
    // T::count must be a valid expression
    T::count;
    // T::count must have type int const
    requires std::is_same_v<int const, decltype(T::count)>;
    // T::count must be usable in a context that requires a constant expression
    typename ::helper<T::count>;
};

struct S1 {
    static constexpr int count = 42;
};
static_assert(HasCount<S1>);

struct S2 {
    int count = 42;
};
static_assert(!HasCount<S2>);

struct S3 {
    static constexpr double count = 3.14;
};
static_assert(!HasCount<S3>);

但实际上,the implementation of concepts in GCC rejects this program:

<source>:20:16: error: invalid use of non-static data member 'S2::count'
 static_assert(!HasCount<S2>);
                ^~~~~~~~~~~~
<source>:18:17: note: declared here
     int count = 42;
                 ^~
<source>:20:16: error: invalid use of non-static data member 'S2::count'
 static_assert(!HasCount<S2>);
                ^~~~~~~~~~~~
<source>:18:17: note: declared here
     int count = 42;
                 ^~

(事实 I believe to be a bug。)