[Bug c++/90679] New: Template specialization with const: “ambiguous template instantiation” error

nikolaus+gcc@nikolaus-demmel.de gcc-bugzilla@gcc.gnu.org
Thu May 30 12:21:00 GMT 2019


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90679

            Bug ID: 90679
           Summary: Template specialization with const: “ambiguous
                    template instantiation” error
           Product: gcc
           Version: 9.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: nikolaus+gcc@nikolaus-demmel.de
  Target Milestone: ---

The below repro-example should compile (IMHO), but it fails with "ambiguous
template instantiation". Same on gcc 7,8,9,trunk according to
https://godbolt.org/z/69Bomq, so probably not a regression.

clang compiles this just fine. See also
https://stackoverflow.com/q/56333067/1813258

Specializing traits<Map<C>> and traits<Map<const C>> works fine, as does
traits<first_type<C>> and traits<first_type<const C>>, so it seems to be this
combination.

In my real code `first_type<C>` has some additional template parameters for
SFINAE.



$ g++-9 -Wall -Wextra foobar.cpp
foobar.cpp: In function 'int main()':
foobar.cpp:36:38: error: ambiguous template instantiation for 'struct
traits<Map<const Foo> >'
   36 |   std::cout << traits<Map<const Foo>>::N << std::endl;
      |                                      ^~
foobar.cpp:24:8: note: candidates are: 'template<class C> struct
traits<Map<first_type<C> > > [with C = const Foo]'
   24 | struct traits<Map<first_type<C>>> {
      |        ^~~~~~~~~~~~~~~~~~~~~~~~~~
foobar.cpp:30:8: note:                 'template<class C> struct
traits<Map<first_type<const C> > > [with C = Foo]'
   30 | struct traits<Map<first_type<const C>>> {
      |        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
foobar.cpp:36:40: error: incomplete type 'traits<Map<const Foo> >' used in
nested name specifier
   36 |   std::cout << traits<Map<const Foo>>::N << std::endl;
      |                                        ^



$ g++-9 -v
Using built-in specs.
COLLECT_GCC=g++-9
COLLECT_LTO_WRAPPER=/usr/local/Cellar/gcc/9.1.0/libexec/gcc/x86_64-apple-darwin16/9.1.0/lto-wrapper
Target: x86_64-apple-darwin16
Configured with: ../configure --build=x86_64-apple-darwin16
--prefix=/usr/local/Cellar/gcc/9.1.0
--libdir=/usr/local/Cellar/gcc/9.1.0/lib/gcc/9 --disable-nls
--enable-checking=release --enable-languages=c,c++,objc,obj-c++,fortran
--program-suffix=-9 --with-gmp=/usr/local/opt/gmp
--with-mpfr=/usr/local/opt/mpfr --with-mpc=/usr/local/opt/libmpc
--with-isl=/usr/local/opt/isl --with-system-zlib --with-pkgversion='Homebrew
GCC 9.1.0' --with-bugurl=https://github.com/Homebrew/homebrew-core/issues
Thread model: posix
gcc version 9.1.0 (Homebrew GCC 9.1.0)



$ cat foobar.cpp
#include <iostream>
#include <type_traits>

class Foo {};

template <class T, class...>
using first_type = T;

template <class C>
class Map {};

template <class C>
struct traits {};

//#define FIX_GCC

#ifdef FIX_GCC
template <typename C>
struct traits<Map<first_type<C, std::enable_if_t<!std::is_const_v<C>>>>> {
  static constexpr int N = 2;
};
#else
template <typename C>
struct traits<Map<first_type<C>>> {
  static constexpr int N = 2;
};
#endif

template <typename C>
struct traits<Map<first_type<const C>>> {
  static constexpr int N = 3;
};

int main() {
  std::cout << traits<Map<Foo>>::N << std::endl;
  std::cout << traits<Map<const Foo>>::N << std::endl;

  return 0;
}


More information about the Gcc-bugs mailing list