Is object construction expression well-formed even if that construction cannot be compiled?

74 Views Asked by At

Suppose we have a non-copyable type X:

struct X
{
    X(X&&) = default;
    X(const X&) = delete;
}

Then, naturally, we cannot copy a container having X as value type:

std::set<X> v;
std::set<X> v2{v}  // error

My question is, whether the expression that involves such a copy is well-formed? For instance, the following expression compiles:

sizeof( std::set<X>{v} )

I am asking since I run into the following problem:

std::cout << std::is_copy_constructible_v< X >;
std::cout << std::is_copy_constructible_v< std::set<X> >;

Which prints out 01. It's a bit counter-intuitive that std::set<X> is "reported" being copy-constructible when in fact it is not (by means of that its copy constructor cannot be called).

1

There are 1 best solutions below

1
n314159 On

That comes from a problem you have, when your container shall support incomplete types. You cannot do both

  • Support incomplete types
  • SFINAE out the special member functions based on copy-ability of the value type

If you support incomplete types, you cannot check in the declaration of the copy constructor if that type is copyable (since it could be incomplete at that point). So, you can always instantiate the copy constructor. But if you do, that will fail in evaluated contextes.

There is a good article on this: https://quuxplusone.github.io/blog/2020/02/05/vector-is-copyable-except-when-its-not/