C++ Logo

std-proposals

Advanced search

Re: is_value_constructible

From: Barry Revzin <barry.revzin_at_[hidden]>
Date: Tue, 4 May 2021 18:47:16 -0400
On Mon, May 3, 2021 at 10:05 AM Bjorn Reese via Std-Proposals <
std-proposals_at_[hidden]> 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>)
any(T&&);

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>)
any(T&&);

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.

Barry

Received on 2021-05-04 17:47:37