C++ 17 How to specialize static function template in class template

Viewed 90

How to do this in G++?

  • Declare a class template ss. [ok]
  • Decalre a static function template f [ok]
  • How to specialize f ? [error]

This code is ok for VC++.

#include<iostream>
#include<utility>
#include<typeinfo>

template<typename T> 
struct ss
{
    template<typename F>
    static constexpr auto f()
    {
        printf("template !\n");
    }

    template<>
    static constexpr auto f<int>()
    {
        printf("int !\n");
    }
};


int main(int argc, const char* argv[])
{
   return ss<int>::f<char>();
}

online : https://godbolt.org/z/qGq6bP

source>:14:14: error: explicit specialization in non-namespace scope 'struct ss<T>'
   14 |     template<>
      |              ^
<source>:15:34: error: template-id 'f<int>' in declaration of primary template
   15 |     static constexpr auto f<int>()
      |                                  ^
<source>: In function 'int main(int, const char**)':
<source>:24:27: error: void value not ignored as it ought to be
   24 |    return ss<int>::f<char>();
      |           ~~~~~~~~~~~~~~~~^~
ASM generation compiler returned: 1
<source>:14:14: error: explicit specialization in non-namespace scope 'struct ss<T>'
   14 |     template<>
      |              ^
<source>:15:34: error: template-id 'f<int>' in declaration of primary template
   15 |     static constexpr auto f<int>()
      |                                  ^
<source>: In function 'int main(int, const char**)':
<source>:24:27: error: void value not ignored as it ought to be
   24 |    return ss<int>::f<char>();
      |           ~~~~~~~~~~~~~~~~^~
Execution build compiler 
1 Answers

This is GCC's issue. According to CWG 727, explicit specialization should be allowed in any scope, including in class scope.

An explicit specialization may be declared in any scope in which the corresponding primary template may be defined (N4868.9.8.2.3 [namespace.memdef], 11.4 [class.mem], 13.7.3 [temp.mem]).

To make it working with GCC, you have to put the explicit specialization in namespace scope, that means you have to explicitly specialize the containing class template ss at the same time too. Or you can use function template helper, e.g.

template <typename F>
constexpr auto foo() 
{
    printf("template !\n");
}
template <>
constexpr auto foo<int>() 
{
    printf("int !\n");
}

template<typename T> 
struct ss
{
    template<typename F>
    static constexpr auto f()
    {
        return foo<F>();
    }

};
Related