https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109888
Bug ID: 109888 Summary: GCC 13 Fails to Compile Code with Explicit Constructor for std::array in Template Class Product: gcc Version: 13.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: vincent.lebourlot at starqube dot com Target Milestone: --- In a C++ codebase, a class String is defined with an explicit constructor that takes a variable number of arguments and constructs a std::array from them. This constructor is being called when creating a std::pair<String, String> in a function call. While this code compiles successfully with GCC 12, it fails to compile with GCC 13. The error messages indicate that the std::array must be initialized with a brace-enclosed initializer, which is not what's happening when forwarding the arguments to the std::array's constructor. This issue seems to be specific to GCC 13 and does not occur in GCC 12. It's unclear whether this is due to changes in the C++ standard or in GCC's implementation of the standard. The code snippet that reproduces this issue is provided below: #include <string> #include <cstring> #include <array> #include <vector> #include <utility> class String { public: template<size_t n>String(const char(&s)[n])noexcept:value(){ if constexpr(n<=16){ std::memcpy(value.data(),s,n);} else{value=std::array<unsigned char,16>{};}} template<typename... Args, std::enable_if_t<std::conjunction_v<std::is_constructible<std::string, Args>...>, int> = 0> explicit String(Args&&... args) : value(std::forward<Args>(args)...) {} private: std::array<unsigned char,16>value; }; int main() { auto check=[&](std::vector<std::pair<String,String>>textInputs){}; check({{{"Hello", "World"}, {"Foo", "Bar"}}}); return 0; } And here's the error message: test.cpp: In function ‘int main()’: test.cpp:20:10: error: converting to ‘const String’ from initializer list would use explicit constructor ‘String::String(Args&& ...) [with Args = {const char (&)[6], const char (&)[6]}; typename std::enable_if<conjunction_v<std::is_constructible<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, Args>...>, int>::type <anonymous> = 0]’ 20 | check({{{"Hello", "World"}, {"Foo", "Bar"}}}); | ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test.cpp:20:10: error: converting to ‘const String’ from initializer list would use explicit constructor ‘String::String(Args&& ...) [with Args = {const char (&)[4], const char (&)[4]}; typename std::enable_if<conjunction_v<std::is_constructible<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, Args>...>, int>::type <anonymous> = 0]’ test.cpp: In instantiation of ‘String::String(Args&& ...) [with Args = {const char (&)[6], const char (&)[6]}; typename std::enable_if<conjunction_v<std::is_constructible<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, Args>...>, int>::type <anonymous> = 0]’: test.cpp:20:10: required from here test.cpp:12:39: error: no matching function for call to ‘std::array<unsigned char, 16>::array(const char [6], const char [6])’ 12 | explicit String(Args&&... args) : value(std::forward<Args>(args)...) {} | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from test.cpp:3: /usr/local/gcc/gcc-13/include/c++/13.1.0/array:94:12: note: candidate: ‘std::array<unsigned char, 16>::array()’ 94 | struct array | ^~~~~ /usr/local/gcc/gcc-13/include/c++/13.1.0/array:94:12: note: candidate expects 0 arguments, 2 provided /usr/local/gcc/gcc-13/include/c++/13.1.0/array:94:12: note: candidate: ‘constexpr std::array<unsigned char, 16>::array(const std::array<unsigned char, 16>&)’ /usr/local/gcc/gcc-13/include/c++/13.1.0/array:94:12: note: candidate expects 1 argument, 2 provided /usr/local/gcc/gcc-13/include/c++/13.1.0/array:94:12: note: candidate: ‘constexpr std::array<unsigned char, 16>::array(std::array<unsigned char, 16>&&)’ /usr/local/gcc/gcc-13/include/c++/13.1.0/array:94:12: note: candidate expects 1 argument, 2 provided test.cpp: In instantiation of ‘String::String(Args&& ...) [with Args = {const char (&)[4], const char (&)[4]}; typename std::enable_if<conjunction_v<std::is_constructible<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, Args>...>, int>::type <anonymous> = 0]’: test.cpp:20:10: required from here test.cpp:12:39: error: no matching function for call to ‘std::array<unsigned char, 16>::array(const char [4], const char [4])’ 12 | explicit String(Args&&... args) : value(std::forward<Args>(args)...) {} | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/local/gcc/gcc-13/include/c++/13.1.0/array:94:12: note: candidate: ‘std::array<unsigned char, 16>::array()’ 94 | struct array | ^~~~~ /usr/local/gcc/gcc-13/include/c++/13.1.0/array:94:12: note: candidate expects 0 arguments, 2 provided /usr/local/gcc/gcc-13/include/c++/13.1.0/array:94:12: note: candidate: ‘constexpr std::array<unsigned char, 16>::array(const std::array<unsigned char, 16>&)’ /usr/local/gcc/gcc-13/include/c++/13.1.0/array:94:12: note: candidate expects 1 argument, 2 provided /usr/local/gcc/gcc-13/include/c++/13.1.0/array:94:12: note: candidate: ‘constexpr std::array<unsigned char, 16>::array(std::array<unsigned char, 16>&&)’ /usr/local/gcc/gcc-13/include/c++/13.1.0/array:94:12: note: candidate expects 1 argument, 2 provided