在C++范型编程中如何只特化类的一个成员函数
我们知道在C++模板编程中如果我们特化或是偏特化某个模板类, 我们需要重写整个模板类中的所有函数, 但是这些代码通常是非常相似的, 甚至在某些情况下可能只有一两个函数会不一样,其他函数都是一样的。在这种情况下,同时存在多份相同的代码,对我们维护这些代码是非常不利的, 我们最好只需要特化其中不一样的那个函数。
比如下面这个模板类:
template<typename T, unsigned B>
struct Base
{
//other function
//....
void Func(){ cout << "primary function" << endl; }
};
void test1()
{
Base<int, 1> a;
a.Func();
Base<int, 16> b;
b.Func();
}
int main()
{
test1();
}
只有当B等于16时, Func这个函数需要特化, 但是其他函数无论什么情况下都是一样的。
下面是我们的一些可能解决方案:
方法1:
template<typename T>
struct Base<T, 16>
{
//other function
//....
void Func(){ cout << "specialization function" << endl; }
};
点评:通过偏特化实现,需要重写所有的类成员方法。
方法2:
template<typename T, unsigned B>
struct Base
{
//other function
//....
void Func()
{
if(B == 16)
{
cout << "primary function" << endl;
}
else
{
cout << "specialization function" << endl;
}
}
};
点评: 通过运行时判断, 容易理解,但是相对低效。
方法3:
template<typename T, unsigned B>
struct Base
{
//other function
//....
void Func()
{
#if B!=16
cout << "primary function" << endl;
#else
cout << "specialization function" << endl;
#endif
}
};
点评: 试图通过预编译来实现,但是这个方法是错误的。C++模板编译包括预编译,语法检查,模板实例化等阶段,在预编译阶段模板参数都还没有实例化呢。
方法4:
template<typename T, unsigned B>
struct Base
{
//other function
//....
template<unsigned S>
struct FuncObj
{
void operator()()
{
cout<<"primary function"<<endl;
}
};
template<>
struct FuncObj<16>
{
void operator()()
{
cout<<"specialization function"<<endl;
}
};
FuncObj<B> Func;
};
点评: 通过成员类以防函数的形式特化, 增加了类成员变量。
方法5:
template<typename T, unsigned B>
struct Base
{
//other function
//....
template<unsigned N>
void FuncImpl()
{
cout<<"primary function"<<endl;
}
template<>
void FuncImpl<16>()
{
cout<<"specialization function"<<endl;
}
void Func()
{
FuncImpl<B>();
}
};
点评:通过类成员模板函数特化来实现。
方法6:
template<typename T, unsigned B>
struct Base
{
//other function
//....
template<unsigned N>
class Int2Type
{
enum { value = N };
};
template<unsigned V>
void FuncImpl(const Int2Type<V>)
{
cout<<"primary function"<<endl;
}
void FuncImpl(const Int2Type<16>)
{
cout<<"specialization function"<<endl;
}
void Func()
{
FuncImpl(Int2Type<B>());
}
};
点评: 通过将int根据值的不同转成不同的类型,然后通过函数重载实现。
方法7:
namespace
{
template <bool,typename T,typename> struct conditional { typedef T type; };
template <typename T,typename U> struct conditional<false,T,U> {typedef U type; };
}
template<class T, unsigned B>
struct Base
{
//other function
//....
void Func ()
{
typedef typename ::conditional<B!=16,primary_t,spec_t>::type type;
Func_impl(type());
}
private:
struct primary_t { };
struct spec_t  
补充:软件开发 , C++ ,