Date: Sun, 2 Oct 2022 16:58:32 -0500
On Sun, Oct 2, 2022 at 4:47 PM Edward Catmur via Std-Discussion <
std-discussion_at_[hidden]> wrote:
> On Sun, 2 Oct 2022 at 22:00, Aleksander Maciej Miera via Std-Discussion <
> std-discussion_at_[hidden]> wrote:
>
>> Hello,
>>
>> While fiddling with template metaprogramming I managed to run into an
>> issue related to some std:: containers and type traits. As far as I have
>> researched it, it is a known (although not obvious at first) shortcoming.
>>
>> Consider the following code snippet:
>>
>> #include <type_traits>
>> #include <memory>
>> #include <vector>
>>
>> struct Copyable{};
>> using MoveOnly = std::unique_ptr<Copyable>;
>>
>> static_assert(!std::is_copy_constructible_v<std::vector<MoveOnly>>);
>>
>> (BTW, the vector is used here as an example, but the list and
>> forward_list also behave the same way for the same reason)
>>
>> Counter-intuitively, the static assert fails. This stems from the fact
>> that the vector's copy constructor is not a function template; thus it
>> cannot be SFINAEd (everything can be a verb if one tries hard enough ;))
>> away, because it's always declared.
>>
>
> Since C++20, the copy constructor can be constrained:
>
> vector(vector const&) requires std::copyable<T>;
>
> I think this would solve your issue. This would require the containers
> general requirements to lift this requirement (on `X u(a)`, that `T` is
> Cpp17CopyInsertable, etc.) from a precondition to a constraint. There are
> probably quite a few clauses that would need to be considered in such an
> effort.
>
The issue is that vector<T> supports T being incomplete. So if you did
that, then:
struct Node;
vector<Node> nodes;
Would instantiate the copy constructor which would error on Node being
incomplete. So you'd have to come up with a way for vector<Incomplete> to
still work.
Barry
std-discussion_at_[hidden]> wrote:
> On Sun, 2 Oct 2022 at 22:00, Aleksander Maciej Miera via Std-Discussion <
> std-discussion_at_[hidden]> wrote:
>
>> Hello,
>>
>> While fiddling with template metaprogramming I managed to run into an
>> issue related to some std:: containers and type traits. As far as I have
>> researched it, it is a known (although not obvious at first) shortcoming.
>>
>> Consider the following code snippet:
>>
>> #include <type_traits>
>> #include <memory>
>> #include <vector>
>>
>> struct Copyable{};
>> using MoveOnly = std::unique_ptr<Copyable>;
>>
>> static_assert(!std::is_copy_constructible_v<std::vector<MoveOnly>>);
>>
>> (BTW, the vector is used here as an example, but the list and
>> forward_list also behave the same way for the same reason)
>>
>> Counter-intuitively, the static assert fails. This stems from the fact
>> that the vector's copy constructor is not a function template; thus it
>> cannot be SFINAEd (everything can be a verb if one tries hard enough ;))
>> away, because it's always declared.
>>
>
> Since C++20, the copy constructor can be constrained:
>
> vector(vector const&) requires std::copyable<T>;
>
> I think this would solve your issue. This would require the containers
> general requirements to lift this requirement (on `X u(a)`, that `T` is
> Cpp17CopyInsertable, etc.) from a precondition to a constraint. There are
> probably quite a few clauses that would need to be considered in such an
> effort.
>
The issue is that vector<T> supports T being incomplete. So if you did
that, then:
struct Node;
vector<Node> nodes;
Would instantiate the copy constructor which would error on Node being
incomplete. So you'd have to come up with a way for vector<Incomplete> to
still work.
Barry
Received on 2022-10-02 21:58:47