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

C++ 概念是否需要constexpr值或函数?,c++,c++-concepts,C++,C++ Concepts,因此,我想做一些高级类型级别的黑客,我真的希望能够编写一个概念,要求一个类型有一个与之相关联的constepr int值,稍后我可以在与integerstd::array模板参数相同的概念中使用它 写作是可能的 template<typename T> concept bool HasCount = requires { typename T::count; }; 在GCC 7.3.0上编译时未使用“错误:在'int'之前应使用主表达式” 另一次失败的尝试:可以编写此代码,

因此,我想做一些高级类型级别的黑客,我真的希望能够编写一个概念,要求一个类型有一个与之相关联的
constepr int
值,稍后我可以在与integer
std::array
模板参数相同的概念中使用它

写作是可能的

template<typename T>
concept bool HasCount = requires {
    typename T::count;
};
在GCC 7.3.0上编译时未使用“错误:在'int'之前应使用主表达式”

另一次失败的尝试:可以编写此代码,这需要
静态int T::count()

模板
概念bool hascont=需要{
{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)
};
模板
概念bool hascont=需要{
{T::count()}->constexpr int;
{T::count()constexpr}->int;//或此
{CONTXPRPR::COUNTHEOR(})}-int;/或(请原谅我模糊GCC而不是阅读手册,不像Perl C++是一个经验科学)
};

所以,我想知道是否有可能要求一个概念表达式是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>);
#包括
#包括
使用helper=void的模板;
模板
概念bool hascont=需要{
//T::count必须是有效的表达式
T::计数;
//T::count必须具有int const类型
需要std::is_same_v;
//T::count必须在需要常量表达式的上下文中可用
typename::helper;
};
结构S1{
静态constexpr int count=42;
};
静态断言(hascont);
结构S2{
整数计数=42;
};
静态断言(!hascont);
结构S3{
静态constexpr重复计数=3.14;
};
静态断言(!hascont);
但实际上:

:20:16:错误:非静态数据成员“S2::count”的使用无效
静态断言(!hascont);
^~~~~~~~~~~~
:18:17:注:此处声明
整数计数=42;
^~
:20:16:错误:非静态数据成员“S2::count”的使用无效
静态断言(!hascont);
^~~~~~~~~~~~
:18:17:注:此处声明
整数计数=42;
^~

(这是事实。)

不知道是否可以直接用概念编写,但traits是可以做到的,然后在概念中使用它。不是每天你都会为Stackoverflow答案编写十几行代码。编译错误看起来像是因为你。有一件事我真的不明白,那就是为什么需要前面的
助手。如果我把
helper
(没有
)作为
hascont
的第一行,我不会得到任何编译错误,但是如果我把它作为第二行(在
t::count;
之后移动),我会得到错误
t::helper不是一个类型
,如果我把它作为最后一行(只需从代码中删除
)我得到的
std::helper尚未声明
。名称空间是否以某种方式从一行传递到下一行?。。。奇怪。另外,谢谢,但我想说的是,自从写了那篇文章之后,我找到了一种不同的、技术稍低的方法来解决我的实际问题:为了方便地定义表示各种数据库查询结果集的类型安全结构。@jcarpenter2我没有忘记
S2
中的
static
,故意忽略测试概念是否正确地不允许这种类型。是的,名称查找错误取决于需求的顺序。
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)
};
#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>);
<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;
                 ^~