On Mon, May 3, 2021 at 10:05 AM Bjorn Reese via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
On 2021-05-02 18:56, Arthur O'Dwyer wrote:

The full hand-written example is:

   requires (constructible_from<AlphableRef, T, Args...>
             and not same_as<remove_cvref_t<T>, AlphableRef)

With my proposal

   requires(value_constructible<AlphableRef, T, Args...>)

I am not too concerned about source code size though.

I want to provide a type trait that communicates intent.

I actually think the original communicates intent better.

One problem with having a trait is you need to name the trait. Maybe there's a really good name for the trait, but I don't think "value constructible" is it. We already have "value initialization", which this is not at all related to, and that's a real problem.

But the other problem is that the intent is... exactly to restrict same-type. I don't think there's a better way to express that intent other than literally that. For instance, let's take std::any. Which would have a constructor today like:

template <copy_constructible T>
    requires (not is_specialization_of_v<remove_cvref_t<T>, in_­place_­type>)
         and (not same_as<remove_cvref_t<T>, any>)

Personally, I think that communicates the intent really well. I'm annoyed that I have to do this thing at all, but given that I have to do it, I'm not sure this is especially bad?

Now, what does this look like with your trait? In this particular case, maybe we collapse together copy_constructible and the "not same_as"?

template <typename T>
    requires value_constructible<any, XX, YY> and
        (not  is_specialization_of_v<remove_cvref_t<T>, in_­place_­type>)

What do we put in XX and YY? XX kind of has to be remove_cvref_t<T>, but would YY be T? T const&? remove_reference_t<T> const&? It doesn't really... work that cleanly?

Now, "not same_as<remove_cvref_t<T>, U>" is a mouthful and is something that comes up a lot (as you point out). And we do have papers that propose concepts to streamline that part of the check (P2199 spells this "distinct_from<T, U>" and P2196 spells this "not similar<T, U>"). I think those are the right way to go here.