явная специализация шаблона функции (который является членом шаблона класса) приводит к «частичной специализации не допускается» ошибка, почему?

Я работаю над Visual Studio 2015 community edition

скажем, у меня есть простой класс, подобный этому:
(Пример ниже «должен быть» компилируемым, потому что он включает в себя все необходимые вещи, к сожалению, он выдает ошибку).

#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;
}

Ошибка:

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

Я считаю себя программистом-младшим, поэтому, конечно, я ошибаюсь, но я считаю, что оба erase<class_foo<T>::tag_aaa>() а также erase<class_foo<T>::tag_bbb>() явные специализации template <typename tag> void erase(); функция. И как таковые, они разрешены. Я считаю, что эта ошибка из-за какого-то плохого синтаксиса, но я не могу найти ошибку.

Вопрос:

  • То, что я пытаюсь сделать, разрешено?
  • Если да, что я делаю не так?
  • Если да, каков правильный синтаксис для специализации этой функции (erase)?

2

Решение

Это похоже на полную специализацию функции шаблона, но это все еще частичная специализация, следовательно, ошибка компиляции.

Почему это? Ну, посмотрите на эту специализацию:

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

Вы сказали, что это явная специализация, но есть еще параметр шаблона для заполнения! Там есть параметр T еще предстоит узнать. Так что специализация … это еще шаблон? Это частичная специализация!

Частичная специализация функции не допускается по многим причинам. Одним из них является то, что он не будет хорошо играть с перегрузкой.

Чтобы эффективно специализировать функцию, вы не должны оставлять параметр шаблона известным, например:

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

Но это не то, что вы хотите.


Вот как я могу решить эту проблему. Используйте перегрузку вместо специализации:

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
}
};

Вместо того, чтобы вызывать такие, как это:

erase<tag_aaa>(); // with specialization

Вы должны вызвать это так:

erase(tag_aaa{}); // with overloading
2

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector