我有一个类似于此的访客类:
struct Visitor
{
template <typename T>
void operator()(T t)
{
...
}
void operator()(bool b)
{
...
}
};
显然, operator()(bool b)
旨在成为上述模板功能的专业化。
但是,它没有我以前在其中看到的 template<>
语法,将其声明为模板特化。但它确实可以编译。
这样安全吗?这是对的吗?
答案 0 :(得分:19)
您的代码不是模板专业化,而是非模板化的功能。那里有一些差异。非模板化的operator()将优先于模板化版本(对于完全匹配,但类型转换不会在那里发生),但您仍然可以强制调用模板化函数:
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
}
答案 1 :(得分:5)
这里有你的功能超载;要获得模板特化,您确实需要template <>
语法。但是,您应该知道这两种方法,即使它们看起来相同,也略有不同,甚至编译器在选择正确的函数时也可能会丢失。列出所有可能的案例对于这个答案来说有点太长了,但你可能想检查一下这个问题的Herb Sutter GoTW #49。
答案 2 :(得分:4)
哦,它会编译。它不会是模板功能。您将拥有常规的非模板功能,而不是模板专业化。
这是安全的,实际上也可能是你想要的。访问者模式通常通过重载来实现。专业化功能模板isn't really a good idea anyway.
答案 3 :(得分:2)
您所做的不是模板序列化,而是函数重载。这很安全。
P.S。在不知道你想要实现的目标的情况下,很难说它是否正确。请记住,无论是模板还是重载函数,都会在编译时选择运算符。如果需要运行时调度,则需要多态,而不是重载。好吧,无论如何你可能都知道;以防万一。
答案 4 :(得分:2)
你有
void operator()(bool b)
不是
模板化功能template< typename T > void
operator()(T t)
这是一个单独的
重载的基本模板
上述您可以对template<> void operator(int i)
中的第二个进行完全专业化,只有在void operator()(bool b)
不匹配时才会考虑。
基本模板的特化用于选择要调用的基本模板方法。但是在你的情况下,你有一个非模板化的方法,将首先考虑。
文章Why Not Specialize Function Templates?非常好地解释了如何选择该方法。
在sumary:
示例:
#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