3
votes
class Myclass
{

    template <typename T>
    static T func()
    {
        T obj;
        return obj;
    }

    template<>
    static int func<int>()
    {

    }

};

I wrote above class and tried to compile it. I got following error:

error: explicit specialization in non-namespace scope 'class Myclass'
error: template-id 'func' in declaration of primary template

Then I moved out my static function out side the class like this:

namespace helper 
{
    template <typename T>
    static T func()
    {
        T obj;
        return obj;
    }

    template<>
    static int func<int>()
    {

    }
}

class Myclass
{
  template <typename T>
  static T func()
  {
      helper::func<T>();
  }

};

I got following error:

error: explicit template specialization cannot have a storage class
In static member function 'static T Myclass::func()':

Then of course I inline my specialized function and it worked.

namespace helper 
{
    template <typename T>
    static T func()
    {
        T obj;
        return obj;
    }

    template<>
     inline int func<int>()
    {

        return 1;
    }
}

class Myclass
{
  template <typename T>
  static T func()
  {
      helper::func<T>();
  }

};

My questions are:
1) Why can't we specialize static member functions inside the class.
2) Why can't we have static template specialized functions

2
@tobi if you go through entire story, you will find that I had to put helper coz i couldn't specialize my static member function.gaurav bharadwaj
yeah sorry. I read it all but somehow when I reached the end I already forgot the beginning. sorry for that ;)463035818_is_not_a_number
I think part of the confusion here is the term “namespace scope”. That doesn’t mean “inside a block declared with namespace”; it means “not inside a class, struct, union, function, etc.”. The beginning of the file is at namespace scope, because anything you put there will be in the global namespace instead of a class or something.Daniel H

2 Answers

2
votes

Honestly, the real answers to both questions are probably "because."

You can specialize a member function template, it just has to be outside of the class and cannot use the static keyword:

struct Myclass {
    template <class T>
    static T func() {
        T obj{};
        return obj;
    }
};

template <>
int Myclass::func<int>() { return 42; }

Both are mostly grammatical reasons. It's just one of those things that you have to remember.

0
votes

To my knowledge C++ does not allow member template specialization at class level. The specializations must be provided at namespace level, so you could declare the specialization outside the class:

// myclass.h
class MyClass
{
public:

    template <class T>
    void test(T )
    {
        std::cout << "non-specialized test" << std::endl;
    }

    template <class T>
    static T myfunc()
    {
        std::cout << "non-specialized myfunc" << std::endl;
        return T{};
    }
};


template <>
inline void MyClass::test(double t)
{
    std::cout << "specialized test" << std::endl;
}

template <>
static double MyClass::myfunc();

/*template <>
static inline void MyClass::myfunc(double )
{
    std::cout << "specialized myfunc" << std::endl;
}*/

Then you provide the implementation in the source file:

// myclass.cpp

template <>
static double MyClass::myfunc()
{
    std::cout << "specialized myfunc" << std::endl;
    return 0.0;
}

Alternatively, you could inline myfunc() in the header file (just like test() function).

Regarding your second question, I tried it in VS2015 and it worked. The only problem is that you are missing return values.