1

Consider the following class template:

template <typename> 
struct S 
{
    template <typename T>
    void f(T) { /* ... */ }
};

It is possible to provide a explicit instantiation definition (or declaration via extern template) of both S itself and S::f:

template struct S<int>;
template void S<int>::f<int>(int);

But what if instead of a regular member function template we had the exact same situation with a constructor template?

template <typename> 
struct S 
{
    template <typename T>
    S(T) { /* ... */ }
};

According to Clang, it is still possible to provide an explicit instantiation definition for S itself, but not for the constructor:

template struct S<int>;       // OK
template S<int>::S<int>(int); // ERROR (!)
error: out-of-line constructor for 'S' cannot have template arguments
template S<int>::S<int>(int);
                 ^~~~~~

On the other hand, GCC seems to accept both definitions. See this live example on godbolt.org.


Is a definition such as template S<int>::S<int>(int) legal, or is Clang correct in rejecting it?

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • 1
    I think in general, GCC accepts a lot more stuff than Clang. Clang is usually a lot more stringent, though I think there was some option about allowing C++ "extensions" to the specs like the ones that GCC accepts. – Vesk Mar 17 '23 at 02:12
  • 1
    No, the template argument list in the c'tor declarator-id is [not valid](https://stackoverflow.com/q/63513984/817643) after C++20. Never really was meant to be valid before, but accidently became such for a while. This is tagged LL, so I dunno if you really figured out how fix the code, but `S::S(int)` is valid as a declarator in the explicit instantiation. Actually, any c'tor where its template argument is deducible from the c'tor function argument can be explicitly instantiated. – StoryTeller - Unslander Monica Mar 17 '23 at 03:25
  • @StoryTeller-UnslanderMonica: in my actually use case the template parameter of the constructor is not part of the function parameter list, as it's an `enable_if` constraint. Any luck there? – Vittorio Romeo Mar 17 '23 at 16:32
  • Sadly no. I suppose one option could be to make the constraint into an unused, defaulted, function parameter type (c++03, retro style). But that's a shot in the dark because I dunno the overload set, so it may not be pleasant either. – StoryTeller - Unslander Monica Mar 17 '23 at 16:51
  • 1
    Can you edit your code to show the actual use case? I'm having a hard time understanding how you can have a constructor template that has a non-deducible template parameter and is nevertheless usable. – Brian Bi Mar 18 '23 at 00:33

0 Answers0