【问题标题】:Checking for constexpr in a concept检查概念中的 constexpr
【发布时间】:2020-11-29 06:02:52
【问题描述】:

我刚开始做概念。检查表达式的语法非常有用,它消除了我使用 sfinae 的许多样板。但是我想知道如何检查表达式是否可以在 constexpr 上下文中使用。有时这些表达式会导致无效。我可以想象的方式看起来像这样,没有注释 constexpr 关键字:

template<typename T>
concept foo = requires(T t) {
    /* constexpr */ { t.bar(); } -> std::same_as<void>;
    /* constepxr */ { T::foo; };
}

但是,我非常怀疑这是正确的语法。有没有一种简单的方法来检查概念中表达式的 constexpr-ness?

我不想检查 constexpr 函数的评估是否对于t 的所有可能值都不会失败,我想知道我是否可以将该表达式放在编译器期望的地方可在编译时评估。

【问题讨论】:

  • 您始终可以使用逗号运算符来更改结果类型,constexpr int x = (t.bar(), 0);
  • 我认为一般情况下这是不可能的 - t.bar()constexpr-ness 可能取决于 t。如果我们喜欢... struct X { int i; constexpr void bar() { if (i &lt;= 0) throw 42; }};
  • @Barry hmm... 但是该函数被标记为 constexpr,因此它可以在 constexpr 上下文中调用。从语法上讲,它是允许的。并且具有正确的值,它不会抛出。我认为抛出 constexpr 函数更像是运行时要求,而如果函数在 constexpr 上下文中完全可用,则更像是编译时要求。
  • @Barry 喜欢,我不想确保函数对于所有可能的值都不会失败,我只想知道该函数是否可以在需要编译时评估的表达式中使用。
  • @GuillaumeRacicot 我打算提出 constexpr 通常在运行时评估的论点,这就是为什么不应该允许检查 constexpr 但你提出了一个很好的论点,我认为检查一个表达式,看看它是否允许在仅 constexpr 的上下文中(例如数组维度)。

标签: c++ constexpr c++20 c++-concepts


【解决方案1】:

我认为可以使用std::bool_constant创建预期的概念,它的特性是在其非常数表达式的参数中替换失败不是编译错误,而只是使概念false

建议的解决方案是

#include <concepts>
#include <type_traits>

template<typename T>
concept HasConstexprVoidBar = 
requires(T t) {
    { t.bar() } -> std::same_as<void>;
    { std::bool_constant<(T{}.bar(), true)>() } -> std::same_as<std::true_type>;
};

struct A {
    constexpr void bar() {}
};

struct B {
    void bar() {}
};

int main() {
    // concept check passes for constexpt A::bar()
    static_assert( HasConstexprVoidBar<A> );
    // concept check fails for B::bar()
    static_assert( !HasConstexprVoidBar<B> );
}

在这里,对于具有 constexpr void 方法 bar 的结构 A 成功验证了概念 HasConstexprVoidBar,对于不具有 B 方法的结构 B,计算结果为 false

演示:https://gcc.godbolt.org/z/nsx9z99G4

【讨论】:

  • 这符合我的要求。语法有点复杂,但有效。非常感谢。
猜你喜欢
  • 1970-01-01
  • 2018-04-19
  • 2019-07-01
  • 2021-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多