模板专业需要模板<>语法?
-
06-09-2019 - |
题
我有一个类似于此的访客课程:
struct Visitor
{
template <typename T>
void operator()(T t)
{
...
}
void operator()(bool b)
{
...
}
};
清楚地, operator()(bool b)
旨在作为前面模板函数的专业化。
但是,它没有 template<>
我曾经看过它的语法,将其声明为模板专业化。但这确实是编译的。
这是安全的吗?这个对吗?
解决方案
您的代码不是模板专业化,而是一个非模板功能。那里有一些差异。非模拟运算符()将优先于模板版本(对于确切的匹配,但是类型转换不会在此进行),但是您仍然可以强制调用模板函数:
class Visitor
{
public: // corrected as pointed by stefanB, thanks
template <typename T>
void operator()( T data ) {
std::cout << "generic template" << std::endl;
}
void operator()( bool data ) {
std::cout << "regular member function" << std::endl;
}
};
template <> // Corrected: specialization is a new definition, not a declaration, thanks again stefanB
void Visitor::operator()( int data ) {
std::cout << "specialization" << std::endl;
}
int main()
{
Visitor v;
v( 5 ); // specialization
v( true ); // regular member function
v.operator()<bool>( true ); // generic template even if there is a non-templated overload
// operator() must be specified there (signature of the method) for the compiler to
// detect what part is a template. You cannot use <> right after a variable name
}
在您的代码中没有太大的区别,但是如果您的代码需要传递模板参数类型,它将变得更有趣:
template <typename T>
T g() {
return T();
}
template <>
int g() {
return 0;
}
int g() {
return 1;
}
int main()
{
g<double>(); // return 0.0
g<int>(); // return 0
g(); // return 1 -- non-templated functions take precedence over templated ones
}
其他提示
您在这里拥有的是功能超载;为了获得模板专业化,您确实需要 template <>
句法。但是,您应该意识到,这两种方法,即使它们似乎似乎相同,也有明显的不同,甚至在选择正确的呼叫函数时,编译器也可能会丢失。列出所有可能的情况将有点太长,但您可能需要检查 Herb Sutter Gotw#49 就此主题而言。
哦,它会编译。它不会是模板函数。您将具有常规的非模板功能,而不是模板专业化。
它是安全的,实际上也可能是您想要的。访问者模式通常通过过载来实现。专门化功能模板 无论如何,这并不是一个好主意。
您所做的不是模板序列化,而是功能超载。这是安全的。
ps很难说是否正确,不知道您要实现的目标。请记住,无论是模板或超载功能,您的操作员都将在编译时间中选择。如果您需要运行时间调度,则需要多态性,而不是超载。好吧,您可能还是知道。以防万一。
你有
void operator()(bool b)
那是非模板函数template< typename T > void operator()(T t)
这是一个单独的基本模板,使上述超载
您可以像在 template<> void operator(int i)
只有在 void operator()(bool b)
不匹配。
基本模板的专业化用于选择要调用哪些基本模板方法。但是,在您的情况下,您有一种非策略方法,将首先考虑。
文章 为什么不专门化功能模板? 很好地解释了如何选择该方法。
Sumary:
- 非模板功能首先考虑(这是您的普通运算符()(bool))
- 函数碱模板第二次检查(这是您的模板函数),选择了最专业的基本模板,然后如果它具有专业化的专业化,则使用专业化的类型,否则基本模板与“正确”类型一起使用(请参阅文章中的解释)
例子:
#include <iostream>
using namespace std;
struct doh
{
void operator()(bool b)
{
cout << "operator()(bool b)" << endl;
}
template< typename T > void operator()(T t)
{
cout << "template <typename T> void operator()(T t)" << endl;
}
};
// note can't specialize inline, have to declare outside of the class body
template<> void doh::operator()<>(int i)
{
cout << "template <> void operator()<>(int i)" << endl;
}
template<> void doh::operator()<>(bool b)
{
cout << "template <> void operator()<>(bool b)" << endl;
}
int main()
{
doh d;
int i;
bool b;
d(b);
d(i);
}
您会收到电话:
operator()(bool b) <-- first non template method that matches
template <> void operator()(int i) <-- the most specialized specialization of templated function is called