Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explicit template specialization cannot have a storage class - member method specialization

Tags:

c++

Say I have the following code in Visual Studio

class foo
{
public:
    template<typename t>
    void foo_temp(int a , t s_)
    {
        std::cout << "This is general tmeplate method";
    }

    template<>
    static void foo_temp(int a , int s)
    {
        std::cout << "This is a specialized method";
    }
};


int main()
{
    foo f;
    f.foo_temp<std::string>(12,"string");
}

Now I am attempting to covert this into GCC. Going through other questions on SO I noticed that in GCC member methods cannot be specialized if the class is not specialized. I therefore came up with this solution

class foo
{

    public:
    template<typename t>
    void foo_temp(int a , t s_)
    {
        std::cout << "This is general template method";
    }


};

template <>
/*static*/ void foo::foo_temp<int>(int a, int value) {
    std::cout << "Hello world";
}

Now this seems to do the trick however when I include the static keyword into the statement i get the error

 explicit template specialization cannot have a storage class

Now this thread talks about it but I am still confused on how I could apply that here. Any suggestions on how I can make the last method static ? Also I am still confused as to why templated methods cant be static in GCC ?

This is the visual studio code

class foo
{
public:
    template<typename t>
    void foo_temp(int a , t s_)
    {
        std::cout << "This is general tmeplate method";
    }

    template<>
    static void foo_temp(int a , int s)
    {
        std::cout << "This is a specialized method";
    }
};


int main()
{
    foo f;
    f.foo_temp<std::string>(12,"string");
}
like image 644
James Franco Avatar asked Mar 13 '15 20:03

James Franco


2 Answers

Any suggestions on how I can make the last method static?

You can't; it's unsupported by the language.

Also I am still confused as to why templated methods cant be static in GCC?

They can; they just can't be both static and non-static. Example:

struct foo {
  template<typename T>
  void bar() {}

  template<typename T>
  static void baz() {}
};

int main() {
  foo f;
  f.template bar<void>();
  foo::baz<void>();
}

It's very confusing to me why you must have a static specialization of a (non-static) template member function. I would seriously re-evaluate this code for sanity.

Note, to the question in the comments, it is not possible to have a template specialization of a static member function, because it is not possible to have a template specialization of a member function in this situation at all. (Use overloading instead.)

struct foo {
  template<typename T, typename U>
  static void bar(T, U) {}

  // Error, you'd need to also specialize the class, which requires a template class, we don't have one.
  // template<>
  // static void bar(int, int) {}
  // test.cpp:2:12: error: explicit specialization of non-template ‘foo’
  //     2 | struct foo {
  //       |            ^
  
  // Partial specializations aren't allowed even in situations where full ones are
  // template<typename U>
  // static void bar<int, U>(int, U) {}
  // test.cpp:14:33: error: non-class, non-variable partial specialization ‘bar<int, U>’ is not allowed
  //   14 |   static void bar<int, U>(int, U) {}
  //      |                                 ^

  // Instead just overload
  template<typename U>
  static void bar(int, U) {}
};
like image 159
OmnipotentEntity Avatar answered Oct 06 '22 00:10

OmnipotentEntity


Did you try good old fashioned overloading? Don't make the static method a template at all and let overloading priority take care of picking it.

like image 40
Mark B Avatar answered Oct 05 '22 23:10

Mark B