函数模板(它是 class 模板的成员)的显式特化会产生 "partial specialization is not allowed" 错误,为什么?
explicit specialization of a function template (which is a member of a class template) produces "partial specialization is not allowed" error, why?
我正在研究Visual Studio 2015 community edition
假设我有一个像这样的简单 class:
(下面的示例 "should be" 是可编译的,因为它包含所有必要的东西,不幸的是,它会产生错误)。
#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
)?
它看起来像是模板函数的完全特化,但它仍然是部分特化,因此出现编译错误。
这是为什么?嗯,看看这个专业:
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
我正在研究Visual Studio 2015 community edition
假设我有一个像这样的简单 class:
(下面的示例 "should be" 是可编译的,因为它包含所有必要的东西,不幸的是,它会产生错误)。
#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
)?
它看起来像是模板函数的完全特化,但它仍然是部分特化,因此出现编译错误。
这是为什么?嗯,看看这个专业:
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