1

How do I write a concept that demands that the class has a noexcept constructor? For example, the following static_assert is true in Clang 15.0.7, although I feel that it shouldn't.

class Ragdoll {
    int age_ = -1;
public:
    Ragdoll(int age) /* noexcept */ : age_(age) {}

    int meow() const;
    int lose_hair();
};

template<typename Cat>
concept cat = requires(Cat cat) {
    noexcept(Cat{42});
    { cat.meow() } -> std::same_as<int>;
};

static_assert(cat<Ragdoll>);

What is the noexcept expression doing then anyway in the concept? (Feel free to also link any good concepts tutorials)

Bob__
  • 12,361
  • 3
  • 28
  • 42
levzettelin
  • 2,600
  • 19
  • 32
  • 3
    `noexcept(x)` is an expression evaluating to a `bool` value: either `true` or `false`. Code inside `requires` does not require an expression to return `true`, the code just needs to be valid. – yeputons May 14 '23 at 20:48

2 Answers2

5

You can check if an expression is noexcept in a requires expression with a noexcept before the -> or ;:

template<typename Cat>
concept cat = requires(const Cat cat) {
    { Cat{42} } noexcept;
    // If you wanted the member function to be noexcept too for example
    { cat.meow() } noexcept -> std::same_as<int>;
};
Artyer
  • 31,034
  • 3
  • 47
  • 75
2

Okay, apparently the following works (in the sense that it triggers the static_assert), although I'd prefer to somehow specify it in the requires clause.

template<typename Cat>
concept cat = noexcept(Cat{42}) && requires(Cat cat) {
    { cat.meow() } -> std::same_as<int>;
};
levzettelin
  • 2,600
  • 19
  • 32