C++ 概念:要求策略类中存在静态变量

Arn*_*ler 2 c++ units-of-measurement c++-concepts

我想约束策略类的模板参数。\n也就是说,当我调用 时Foo<policy>,如果策略类不满足我想要的要求,我希望编译器在此处停止。

\n

完整的非工作示例

\n

为了简化问题,我们只考虑策略类必须声明一个静态变量的要求,该静态变量本身满足另一个概念(这里是mp-units 库中的 Acceleration 概念) 。

\n
#include <units/isq/si/si.h>\n\nusing units::isq::Acceleration;\n\n// A policy\nstruct earth\n{\n    // requirement seems to be fulfilled\n    static inline constexpr Acceleration auto gravity = standard_gravity<>;\n};\n\n// Let\'s define a concept because I will need soon to use a set of more than 1 requirements\ntemplate <typename T>\nconcept SphericBody = requires(T)\n{\n  { T::gravity } -> Acceleration;\n};\n\n// The host class that has a constraint of the template argument\ntemplate<SphericBody T>\nclass Foo\n{\n  // ...\n}\n\nint main()\n{\n  Foo<earth> // does not compile :\'(\n}\n
Run Code Online (Sandbox Code Playgroud)\n

它失败并显示以下编译器消息:

\n
\xe2\x80\x98T::gravity\xe2\x80\x99 does not satisfy return-type-requirement\n     { T::gravity } -> units::isq::Acceleration;\n
Run Code Online (Sandbox Code Playgroud)\n

在当前版本的 mp-units 库中,加速概念声明如下:

\n
\xe2\x80\x98T::gravity\xe2\x80\x99 does not satisfy return-type-requirement\n     { T::gravity } -> units::isq::Acceleration;\n
Run Code Online (Sandbox Code Playgroud)\n

我究竟做错了什么?

\n

我知道这个相关问题:C++ Concepts - Can I have a constraining required a function be present in a class? 但它侧重于非静态成员变量。

\n

最小工作示例

\n

根据@HolyBlackCat 的要求,我尽力提供一个最小的工作示例。成员变量现在是一个简单的整数。只需添加 require 子句即可:

\n
#include <units/concepts.h>\n#include <units/isq/dimensions/length.h>\n#include <units/isq/dimensions/time.h>\n\nnamespace units::isq {\n\ntemplate<typename Child, Unit U, typename...>\nstruct dim_acceleration;\n\ntemplate<typename Child, Unit U, DimensionOfT<dim_length> L, DimensionOfT<dim_time> T>\nstruct dim_acceleration<Child, U, L, T> : derived_dimension<Child, U, exponent<L, 1>, exponent<T, -2>> {};\n\ntemplate<typename T>\nconcept Acceleration = QuantityOfT<T, dim_acceleration>;\n\n}  // namespace units::isq\n
Run Code Online (Sandbox Code Playgroud)\n

最小的非工作示例

\n

在这种情况下,需求被导出到一个概念中,并且不再编译。

\n
template <typename T>\nconcept HasGravity = requires(T t)\n{\n  { t.gravity } -> std::same_as<int&>;\n};\n\nstruct myearth\n{\n    int gravity;\n};\n\n// The host class that has a constraint of the template argument\ntemplate<HasGravity T>\nclass Foo\n{};\n\n// using policy_t = Foo<earth> // compiles\n
Run Code Online (Sandbox Code Playgroud)\n

错误:

\n
note: constraints not satisfied\ntest.cpp:45:9:   required for the satisfaction of \xe2\x80\x98HasGravity<T>\xe2\x80\x99 [with T = myearth]\ntest.cpp:45:22:   in requirements with \xe2\x80\x98T t\xe2\x80\x99 [with T = myearth]\ntest.cpp:47:7: note: \xe2\x80\x98t.gravity\xe2\x80\x99 does not satisfy return-type-requirement\n   47 |   { t.gravity } -> IsAcceleration;\n
Run Code Online (Sandbox Code Playgroud)\n

Hol*_*Cat 8

我不熟悉这个库,但我的猜测是这个Acceleration概念拒绝引用。

{ expr } -> concept要求确定类型,就像 by 一样decltype((expr)),这对于您的变量会产生左值引用。


decltype检查表达式的值类别,并添加&到左值类型和&&x值类型(纯右值类型不变)。由于表达式不能具有引用类型,因此不会丢失任何信息。

decltype变量有一个特殊情况 - 对于它们来说,它返回所写的类型,丢弃值类别。通过添加第二对括号,您可以禁用此功能,回到上述行为。