https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115672
Bug ID: 115672 Summary: Incorrect template type parameter deduced in non-deduced context if class template has template template parameter Product: gcc Version: 14.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: s.murthy at outlook dot com Target Milestone: --- Created attachment 58524 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=58524&action=edit Repro source code with static_asserts such that the program compiles This issue is related to Bug 115656 in that the two likely have the same or largely the same underlying cause, but this bug is also distinct because it exists even after circumventing the situation leading to 115656. I chose to report this issue separately because IMHO the effect is rather serious due to incorrect type deduction, but it is obviously up to the maintainers to merge the two issues or to treat them separately. Like 115656, this issue is also a regression: no issues in GCC 10.5; issues in GCC 11.1 and later. Setup: Class template A with a constrained type parameter and a constrained template template parameter. A has ctors for both deducing and non-deducing contexts. When an A object is created in a non-deduced context (after circumventing the ordering issue in 115656), the template type parameter is assigned the type used in the non-deduced ctor call instead of assigning the default specified for the template type parameter. The incorrect type then propagates to all entities carrying that deduced type. E.g., a data member that should be `unsigned` due to that being the default for the template type parameter is instead made `long` because the non-deducing ctor call has long argument. This **even though the template type parameter is constrained to be unsigned integral.** Repro follows. Remove the template template parameter from A and the issues disappear. (Comparison at: https://sigcpp.godbolt.org/z/TG4vva8P5) ---------------------------------------------------------------------------- //stub for use in class template A template<std::unsigned_integral U = unsigned> class dv; template<std::unsigned_integral U = unsigned, template<std::unsigned_integral> class V = dv> struct A { U u_; A(U u) : u_(u) {}; template<std::signed_integral S> A(S s) : u_( s < 0 ? -s : s) {} }; int main() { A a1(45ul); //use deducing-ctor first to circumvent the issue in 115656 static_assert(std::same_as<decltype(a1.u_), unsigned long>); //passes, correct A a2(45l); //U should be unsigned static_assert(std::same_as<decltype(a2.u_), unsigned>); //fails in GCC 11.1+, incorrect static_assert(std::same_as<decltype(a2.u_), long>); //passes in GCC 11.1+, incorrect //a2.u_ = -1; //std::cout << a2.u_ << '\n'; //-1 instead of UINT_MAX in GCC 11.1+ }