Bug 64063 - [DR 1665] Incorrect "ambiguous template specialization" error
Summary: [DR 1665] Incorrect "ambiguous template specialization" error
Status: SUSPENDED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 5.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
: 55136 (view as bug list)
Depends on:
Blocks:
 
Reported: 2014-11-24 23:35 UTC by Jonathan Wakely
Modified: 2016-07-24 23:12 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2014-11-25 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Wakely 2014-11-24 23:35:47 UTC
G++ rejects this explicit instantiation definition as ambiguous:

template<typename T>
struct S
{
  void foo(int) { }
  template<typename U> void foo(U) { }
};

template void S<char>::foo(int);  // XXX


EDG thinks it's OK, clang crashes, and G++ says:


inst.cc:8:15: error: ambiguous template specialization ‘foo<>’ for ‘void S<char>::foo(int)’
 template void S<char>::foo(int);  // XXX
               ^
inst.cc:4:8: note: candidates are: void S<T>::foo(int) [with T = char]
   void foo(int) { }
        ^
inst.cc:5:29: note:                 template<class U> void S<T>::foo(U) [with U = U; T = char]
   template<typename U> void foo(U) { }
                             ^


I think EDG is correct and the diagnostic is wrong, because I'm not referring to any foo<> but rather foo.


Changing the instantiation to be unambiguously a template produces almost the same error (with foo<> replaced by foo<int>) and that definitely isn't ambiguous because one candidate isn't even a function template:

template<typename T>
struct S
{
  void foo(int) { }
  template<typename U> void foo(U) { }
};

template void S<char>::foo<int>(int);  // XXX


inst.cc:8:15: error: ambiguous template specialization ‘foo<int>’ for ‘void S<char>::foo(int)’
 template void S<char>::foo<int>(int);  // XXX
               ^
inst.cc:4:8: note: candidates are: void S<T>::foo(int) [with T = char]
   void foo(int) { }
        ^
inst.cc:5:29: note:                 template<class U> void S<T>::foo(U) [with U = U; T = char]
   template<typename U> void foo(U) { }
                             ^
Comment 1 Jonathan Wakely 2014-11-25 00:02:52 UTC
Apparently EDG instantiates the member function template, which is not what I wanted:

template<typename T>
struct S
{
  void foo(int) { }
  template<typename U> void foo(U);  // undefined
};

template void S<char>::foo(int);  // XXX


"inst.cc", line 8: error: function "S<T>::foo(U) [with T=char, U=int]" cannot
          be instantiated -- no template definition was supplied
  template void S<char>::foo(int);  // XXX
           ^

Is there no syntax for instantiating the non-template?
Comment 2 Jonathan Wakely 2014-11-25 02:36:44 UTC
At http://llvm.org/bugs/show_bug.cgi?id=21661 Richard identified this as http://open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1665
Comment 3 Jonathan Wakely 2014-11-25 02:43:02 UTC
The current handling of the following is still wrong (rejects-valid) independent of DR 1665. It should compile because it can only refer to the template:

template<typename T>
struct S
{
  void foo(int);
  template<typename U> void foo(U) { }
};

template void S<char>::foo<>(int);
Comment 4 Andrew Pinski 2016-07-23 23:18:32 UTC
*** Bug 55136 has been marked as a duplicate of this bug. ***