Having problem understaning a concept in C++ 20

I have this concept:

1
2
3
4
5
6
7
8
template <class T, class U> using CommonType = std::common_type_t<T, U>;
template <class T, class U> concept Common =
requires (T t, U u)
{
	typename CommonType<T, U>; // CommonType<T, U> is valid and names a type
	{ CommonType<T, U>{std::forward<T>(t)} };  // MEANS WHAT?
	{ CommonType<T, U>{std::forward<U>(u)} };  // MEANS WHAT?
}


What I don't understand is the two lines marked with // MEANS WHAT?

I am very grateful for any explanation.

Regards,
Juan

CommonType<T,U>
must have a moving constructor that receives a T or a U

right?
Last edited on
first is a https://en.cppreference.com/w/cpp/language/constraints#Type_requirements "the named type is valid"

second and third are https://en.cppreference.com/w/cpp/language/constraints#Simple_requirements "the expression is valid"

Those two expressions are T{arg}, described in https://en.cppreference.com/w/cpp/language/explicit_cast which request direct-list-initialization (so in simple words, this says common type exists and both T and U are convertible to it)
ok, but why the use of std::forward in


 
{ CommonType<T, U>{std::forward<T>(t)} };


?
Last edited on
Oh, I see, it's an old typo originating from Ranges TS that I fixed for Swappable but forgot for Common. It's requires(T&& t, U&& u), of course, otherwise there's nothing to forward. Fixed.
ok so that was a bug in the documentation got it!

but still, not clear why we need to use forward?
it protects against pathological common_type_t
e.g.
1
2
3
4
5
6
7
8
9
10
struct A {};
struct B {};
struct C {
    C(const A&) {}
    C(A&&) = delete; // don't do this
    C(const B&) {}
};
namespace std {
    template<> struct common_type<A,B> { using type=C; };
}


without forward, the concept is only checking construction of C from lvalue A: https://wandbox.org/permlink/4x7Hc8ZdEi5Y4bEw
with forward, the concept catches this: https://wandbox.org/permlink/i6keCadkOTapLMMj
Last edited on
thanks!
Topic archived. No new replies allowed.