c++type-conversioninitializationc++20c++-concepts

concept or trait to check for copy initialization


I'd like to check how and if an object of type A can be constructed from an object of type B.
I also want to distinguished between direct and copy initialization and thus wrote these concepts:

template<typename A, typename B>
concept can_direct_init_from = requires { A{std::declval<B>()}; };
template<typename A, typename B>
concept can_copy_init_from = requires { A a = std::declval<B>(); };

The first one, I think, is strictly equivalent to std::constructible_from but I don't know of a similar concept for the copy initialization case.
std::convertible_to does not seem to be used for a copy initialization (according to the corresponding traits, it is equivalent to testing a static_cast from B to A).

Besides my version is ill-formed:

error: expected primary-expression before 'a'

AFAU, I can not "declare" variable inside a `requires clause.

Is there a way to test for "is copy initializable from"? Possibly by fixing my concept?


Solution

  • Sounds like std::is_convertible_v<B, A>, a.k.a. std::convertible_to<B, A>. The way that's traditionally implemented is to put the conversion in a function argument:

    template<class T> T produce();
    template<class T> void consume(T);
    
    template<class A, class B>
    concept can_copy_init_from =
      requires { consume<A>(produce<B>()); };