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

时间:2018-05-16 07:25:35

标签: c++ c++-concepts

所以,我想做一些高级的类型级别的hackery,我真的希望能够编写一个概念,要求类型具有与之关联的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;
};

不会使用&#34;错误编译:在&#39; int&#39;&#34;之前预期的primary-expression;在GCC 7.3.0。

另一次尝试失败:可以写这个,这需要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,或者如果没有,是否有理由说明为什么它可以&#39;是可能的,或者如果它不包含在规范中。

1 个答案:

答案 0 :(得分:2)

理论上,这可以通过要求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。)