Implicit copyable requirement of requires expression

97 Views Asked by At

Does the following code requires an implicit copy constructor for T, because the parameters are passed by value? Or does it behave like decltype and there's no real construction involved?

template<typename T>
concept Addable = requires (T a, T b){ a + b; };
2

There are 2 best solutions below

0
Barry On BEST ANSWER

That concept simply checks that a + b is a valid expression. The a and b there are simply invented objects that are lvalues of type T - they are not at all constructed.

If the expression a + b, based on how operator+ is defined, results in copying, then that copy will also be checked as part of seeing if the expression is valid. But otherwise, no.

For instance:

struct A {
    A(A const&) = delete;
    A& operator=(A const&) = delete;
    void operator+(A const&) const;
};

// A is noncopyable, but Addable
static_assert(Addable<A>);

struct B {
    B(B const&) = delete;
    B& operator=(A const&) = delete;
    friend void operator+(B, B) { }
};

// B is noncopyable, but not Addable
// (because invoking + requires copying)
static_assert(!Addable<B>);
0
Nicol Bolas On

The parameters of a requires expression do not impose any requirements on the types of those parameters. They don't require that someone has called a function by passing two Ts. The types don't even have to be publicly constructible.

requires "parameters" are just hypothetical: presuming these things exist, what are they required to do?

The individual requirements in such an expression verify the validity of that expression. a + b needs to be an expression that can compile. Because you didn't add a constraint that verifies anything about the type of that expression, the resulting type of that expression doesn't matter. As long as a + b can compile given two values of type T, the requirement is satisfied.