explicit specialization of a function template (which is a member of a class template) produces "partial specialization is not allowed" error, why?

PatrykB

I am working on Visual Studio 2015 community edition

let's say I have, a simple class like this:
(The example below "should be" a compilable because it include all the necessary stuff, unfortunately, it produces an error).

#include <stdexcept>

template <typename T>
class class_foo
{
// members, methods, constructors. not important stuff...

// helper functions:
private:
    class tag_aaa {}; // to resolve few things at compile-time, not run-time.
    class tag_bbb {}; // - || -

    template <typename tag>
    void erase();

    // for some reason this is not interpreted as an error by my compiler:
    template<>
    void erase<tag_aaa>();

    template<>
    void erase<tag_bbb>();
};

// catch-all-do-nothing "version"
// well, catch-all-throw-an-exception because call to this function is an obvious error.
// that should never occur.
template <typename T>
template <typename tag> inline
void class_foo<T>::erase()
{
    throw std::runtime_error("Very weird error...");
}

template <>
template <typename T> inline
void class_foo<T>::erase<class_foo<T>::tag_aaa>()
{
    // do some stuff... 
}

template <>
template <typename T> inline
void class_foo<T>::erase<class_foo<T>::tag_bbb>()
{
    // do some stuff... 
}

int main()
{
    class_foo<double> bar;

    return 0;
}

The error:

1>D:/develop/workspace/visual_studio/nevada_test_site/source/workspace/nevada_test_site/start.cu(36): error : partial specialization of class "class_foo<T>::erase<class_foo<T>::tag_aaa> [with T=T]" is not allowed

1>D:/develop/workspace/visual_studio/nevada_test_site/source/workspace/nevada_test_site/start.cu(43): error : partial specialization of class "class_foo<T>::erase<class_foo<T>::tag_bbb> [with T=T]" is not allowed

1>D:/develop/workspace/visual_studio/nevada_test_site/source/workspace/nevada_test_site/start.cu(51): warning : variable "bar" was declared but never referenced

I think about myself as a junior-hobbyist programmer, so certainly I am wrong, but I believe that both erase<class_foo<T>::tag_aaa>() and erase<class_foo<T>::tag_bbb>() are explicit specializations of the template <typename tag> void erase(); function. And as such, they are allowed. I believe that this error is due to some bad syntax but I can't find an error.

Question:

  • Is what I am trying to do, allowed?
  • If yes, what am I doing wrong?
  • If yes, what is the correct syntax for specializing this functions (erase)?
Guillaume Racicot

It look like full specialization of a template function but it's still partial specialization, hence the compilation error.

Why is it? Well, look at this specialization:

template <>
template <typename T>
inline void class_foo<T>::erase<class_foo<T>::tag_bbb>() {
    // do some stuff...
}

You said it's a explicit specialization, but there is still a template parameter to fill! There's the parameter T yet to be known. So a specialization... that is still a template? That's a partial specialization!

Partial specialization of function is not allowed, for many reason. One of them is that it won't play nicely with overloading.

To effectively specialize the function, you must leave no template parameter to be known, something like this:

template<>
template<>
inline void class_foo<int>::erase<class_foo<int>::tag_bbb>() {
    // do some stuff...
}

But it's not what you want.


Here's how I'd fix this problem. Use overloading instead of specializing:

template<typename T>
struct class_foo {

private:
    struct tag_aaa {};
    struct tag_bbb {};

    void erase(tag_aaa) {
        // Stuff when tag_aaa
    }

    void erase(tag_bbb) {
        // Stuff when tag_bbb
    }
};

Instead of invoking those like this:

erase<tag_aaa>(); // with specialization

You must invoke it like that:

erase(tag_aaa{}); // with overloading

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Template member function specialization in a template class

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

Template function specialization for template class

Explicit specialization of member function template in source file

Explicit specialization of a function template for a fully specialized class template

explicit specialization for function template c++

Parameterization and "function template partial specialization is not allowed"

Function template overloading vs Explicit specialization

template<> for the explicit specialization of a member enumeration

explicit specialization "..." is not a specialization of a function template

Template specialization for a class member function in order to not use increment operator on bool

Specialization of a template member function of a template class in GCC 7

Explicit instantiation of function template specialization

Is it legal to define a hidden friend in an explicit specialization of an otherwise non-defined member class of a class template?

Explicit specialization of member function with variadic template arguments

Template member specialization in template class

specialization of class member of a template class

template class - member function specialization

Specialization of member function template after instantiation error, and order of member functions

Explicit template specialization for templated constructor of templated class

Class template member specialization

Class template specialization that changes only one member function

Specialization of member function of class template

c++ call template class specialization member function

Template explicit specialization in class using inheritance

error: explicit specialization of undeclared template class

explicit specialization in template class error

How make template member function specialization from inherited class?

Partial specialization of a class template member function