Search code examples
c++language-lawyertemplate-specialization

Explicitly specify additional template arguments - But I have no arguments left to specify


The following code does not compile under clang (tested with version 10.0), but compiles under gcc (tested with version 10.1); C++ version 14. Which of the compilers is correct?

template< typename T > int func(); // (1)
template< typename ... Args > int func();  // (2)
template<> int func<int>() { return 1; }
int main {
  // func<int>();  // (*)
}
  • The error message of clang is:

    function template specialization func ambiguously refers to more than one function template; explicitly specify additional template arguments to identify a particular function template

    My problem is, the function marked with (1) does not have additional template parameters, thus I cannot add additional template parameters. So, how to solve this problem?

  • If I uncomment the line (*), then gcc also refuses to compile this code with the message:

    call of overloaded func<int>() is ambiguous.


Solution

  • The given program(even without the call) is not valid because you're trying to explicitly specialize function template func with information that is not enough to distinguish/disambiguate which func to specialize. A gcc bug report has been submitted here.

    There are 2 ways to solve this depending on which func you want to specialize. Note also that the function call func<int>(); will still be ambiguous. The solution given below is just for specialization and not for call expression.


    Method 1

    My problem is, the function marked with (1) does not have additional template parameters, thus I cannot add additional template parameters. So, how to solve this problem?

    In case, you want to explicitly specialize #1 you can solve the error by moving the explicit specialization above/before #2 as shown below:

    template< typename T > int func(); // (1)
    template<> int func<int>() { return 1; }  //OK NOW, explicitly specialize #1
    template< typename ... Args > int func();  // (2)
    
    int main() {
      
    }
    

    Working demo

    Method 2

    And in case you want to explicitly specialize #2 you should add more template argument in specialization as shown below:

    template< typename T > int func(); // (1)
    
    template< typename ... Args > int func();  // (2)
    template<> int func<int, double>() { return 1; } //OK NOW, explicitly specialize #2
    int main() {
      
    }
    

    Working demo