[英]partial specialization of function templates
在下面的代码段中,
template<typename T1>
void func(T1& t)
{
cout << "all" << endl;
}
template<typename T2>
void func(T2 &t)
{
cout << "float" << endl;
}
// I do not want this
// template<> void func(float &t)
int main()
{
int i; float f;
func(i); // should print "all"
func(f); // should print "float"
return 0;
}
我希望修改模板,通过传递浮动以外的任何类型将打印“all”并传递float将打印“float”。 我不想要模板特化,而是根据输入类型进行相应的部分特化。 我应该怎么做呢。 提前致谢。
那个场景,我现在面临的是,我需要定义以下内容,
template<typename T1>
void func(T1 &t)
{
cout << "t1" << endl;
}
template<typename T2>
void func(T2 &t)
{
cout << "t2" << endl;
}
以下调用应打印“t2”
func(int) // print "t2"
func(float) // print "t2"
func(string) // print "t2"
以下调用应打印“t1”
func(char) // print "t1"
func(xyz) // print "t1"
...
func(abc) // print "t1"
某些类似于上面的分组,很少有人应该调用部分特化实现,而其他人应该调用默认实现。
您可以将函数重载与模板结合使用。 所以:
#include <iostream>
template<typename T>
void func(T& t)
{
std::cout << "all" << std::endl;
}
void func(float& f)
{
std::cout << "float" << std::endl;
}
int main()
{
int i; float f;
func(i); // prints "all"
func(f); // prints "float"
return 0;
}
你不能在C ++中部分专门化函数。
也许这不是你的意思。 您可以使用boost::is_same<T1, T2>
等模板根据给定的模板参数执行条件逻辑。 您还可以在任何其他类型的地方使用T
,例如在typeid(T).name()
:
template <typename T>
void foo(T&) {
if (boost::is_same<T, int>::value)
std::cout << "int lol";
else
std::cout << typeid(T).name();
}
(虽然我不建议使用typeid()。name(),因为它的值不是由标准指定的,并且可能与代码中写入的类型,错位符号或Pokerface的歌词不同。)
附录和其他的回答者一样,我个人会选择模板专业化,或者仅仅是简单的函数重载。 我不知道你为什么反对他们,但这就是他们的目的。
为您的条件写一个类型特征类:
template<class T>
struct IsIntFloatOrString {
enum { value = boost::is_same<T, int>::value
or boost::is_same<T, float>::value
or boost::is_same<T, string>::value };
};
使用boost :: enable_if和disable_if:
template<typename T1>
typename boost::enable_if<IsIntFloatOrString<T1> >::type
func(T1 &t) {
cout << "t1" << endl;
}
template<typename T2>
typename boost::disable_if<IsIntFloatOrString<T2> >::type
func(T2 &t) {
cout << "t2" << endl;
}
正如Tomalak在他的回答中已经说过,你不能部分地专门化模板函数,但如果你将函数改为模板类中的静态成员函数,你就可以做到。
但是,更好的方法是函数重载。
这是如何在没有任何条件的情况下使其工作而没有丑陋的语法a and !b and !c
for enable_if
。
如果我们知道部分特化不起作用而不是使用类,那么让我们使用类吧! 我们应该把它隐藏起来,但我们可以使用它们!
好的,代码:
#include <type_traits>
#include <iostream>
template <typename T>
class is_int_or_float : public std::integral_constant<bool, std::is_same<T, int>::value || std::is_same<T, float>::value> {
};
template<typename T, typename Enable = void> //(2)
struct Helper {
static void go(const T&) {
std::cout << "all"<< std::endl;
}
};
template<typename T>
struct Helper<T, typename std::enable_if<is_int_or_float<T>::value>::type> { // (3)
static void go(const T&) {
std::cout << "int or float" << std::endl;
}
};
template<typename T>
struct Helper<T, typename std::enable_if<std::is_pointer<T>::value>::type> { // (3)
static void go(const T&) {
std::cout << "pointer" << std::endl;
}
};
template<typename T>
void func(const T& arg) {
Helper<T>::go(arg); // (1)
}
int main() {
char c;
int i;
float f;
int* p;
func(c);
func(i);
func(f);
func(p);
}
(1)首先只为每个类型的呼叫助手。 没有专业化的功能。
(2)这里我们添加一个伪参数。 我们不必在调用时指定它,因为它默认为void
(3)在3中我们只允许void
,当我们允许T
和其他任何东西时(或者在我们的情况下是SFINAE)。 一件重要的事情是我们不应该允许某些T
两次或更多次。
笔记:
我们也可以将默认类型更改为std :: true_type,之后我们将能够摆脱std::enable_if
( std::enable_if<some_trait<T>::value>
将更改为some_trait<T>::type
)。 我不确定哪个
此代码使用C ++ 11中的类型特征。 如果您没有c ++ 11支持,您可以编写自己的特征或使用boost
类型特征
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.