A colleague of mine has find a strange compilation error with GCC when one tries to brace initialize a std::vector<Foo> with another, if Foo is move-only but provides a templated constructor, like in the following example:
#include <vector>
struct Foo{
template <class T> Foo(T) {}
Foo(const Foo&) = delete;
Foo(Foo&&) = default;
};
int main(){
std::vector<Foo> v1(std::vector<Foo>{}); // ok
std::vector<Foo> v2{std::vector<Foo>{}}; // compilation error
}
(See code and error on Compiler Explorer.)
Is it a bug? If so, where (within the instantiation process, I guess) is GCC making the mistake? In other words, since the code is ok for all three compilers as soon as one removes the templated construtor, what in the latter trips GCC up?
I think that GCC is correct in rejecting the program for the reasons described below:
std::vectorhas a constructor that takes anstd::initializer_list:Thus when you wrote:
In the above statement, the quoted initializer list ctor of
vectorcan be used/utilised.Moreover, the copy constructor
Foo::Foo(const Foo&)will be used here since from dcl.init.lst:(emphasis mine)
But since the copy constructor is
deletedwe get the mentioned error. You can confirm that this is indeed the case bydefaultingthe copy ctor instead of deleting it as done in this demo and as we can notice there the program works(compiles) without any issues.