https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69235
Bug ID: 69235 Summary: [concepts] Spurious ambiguous template instantiation error on oppositely constrained class template specializations Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: tom at honermann dot net Target Milestone: --- I believe the following test case is well-formed, but gcc trunk (r232017) emits an "ambiguous template instantiation" error for the X<S> specialization. The ambiguity arises from the oppositely constrained partial specializations of template class X. Since the partial specializations are oppositely constrained, an ambiguity should not be possible. The test case exhibits some fragility. The error only occurs when the requires expression in the C concept definition specifies a constrained-type-specifer as the trailing-return-type of the compound-requirement at #3; substituting a non-placeholder simple-type-specifier as is done at #2 by compiling with the AVOID_BOOLEAN_CONCEPT macro defined enables successful compilation. Additionally, compilation is successful (with or without AVOID_BOOLEAN_CONCEPT defined) if the code is adjusted at #6 to pass a fundamental type (char) instead of S as the template argument to X, and at #4 and #5 to pass T rather than the member type T::type in the requires clause. $ cat t.cpp template<typename T> concept bool Boolean() { return requires(T t) { { t } -> bool // #1 }; } template<typename T> concept bool C() { return requires (T t) { #if AVOID_BOOLEAN_CONCEPT { t } -> bool; // #2 #else { t } -> Boolean; // #3 #endif }; } template<typename T> struct X; template<typename T> requires ! C<typename T::type>() // #4 struct X<T> { using type = int; }; template<typename T> requires C<typename T::type>() // #5 struct X<T> { using type = int; }; struct S { using type = char; }; void f() { X<S>::type x; // #6 } $ svn info # From my local svn gcc repo. Path: . Working Copy Root Path: /home/tom/src/gcc-trunk URL: svn://gcc.gnu.org/svn/gcc/trunk Relative URL: ^/trunk Repository Root: svn://gcc.gnu.org/svn/gcc Repository UUID: 138bc75d-0d04-0410-961f-82ee72b054a4 Revision: 232017 Node Kind: directory Schedule: normal Last Changed Author: nathan Last Changed Rev: 232017 Last Changed Date: 2015-12-31 09:07:52 -0500 (Thu, 31 Dec 2015) # Using the gcc version above, the error is produced: $ g++ -c -std=c++1z t.cpp t.cpp: In function ‘void f()’: t.cpp:42:9: error: ambiguous template instantiation for ‘struct X<S>’ X<S>::type x; ^~ t.cpp:28:8: note: candidates are: template<class T> requires predicate(!(C<typename T::type>)()) struct X<T> [with T = S] struct X<T> { ^~~~ t.cpp:33:8: note: template<class T> requires predicate((C<typename T::type>)()) struct X<T> [with T = S] struct X<T> { ^~~~ t.cpp:42:5: error: incomplete type ‘X<S>’ used in nested name specifier X<S>::type x; ^~~~ # Compiling with AVOID_BOOLEAN_CONCEPT defined avoids the spurious error: $ g++ -c -std=c++1z t.cpp -DAVOID_BOOLEAN_CONCEPT; echo $? 0