有些高级脚本语言,如Perl、PL/SQL等,他们的函数参数在调用时都支持命名参数,既在调用时可以不按照顺序传递参数,而是p可以按照参数的名字传递。模板中命名参数的实现如下
#include <iostream>
#include <cstring>
// PolicySelector 的任务是利用typedef将各个模板实参合并到一个单一的类型,即Discriminator;该类型能够根据指定的非缺省类型,改写缺省定义的typedef成员
// PolicySelector <A, B, C, D>生成A,B,C,D作为基类
// Discriminator<>使Policy Seletor可以多次继承自相同的基类
// 中间模板Discriminator的引入是为了一致的处理各个Setter类型(不能直接从多个相同类型的基类继承,但可以借助中间类间接继承)
template<typename Base, int D>
class Discriminator: public Base{
};
template<typename Setter1,
typename Setter2,
typename Setter3,
typename Setter4>
class PolicySelector : public Discriminator<Setter1, 1>,
public Discriminator<Setter2, 2>,
public Discriminator<Setter3, 3>,
public Discriminator<Setter4, 4>{
};
//先定义出不同的策略类。
class DefaultPolicy1 {};
class DefaultPolicy2 {};
class DefaultPolicy3 {
public:
static void doPrint(){
printf("DefaultPolicy3::doPrint()\n");
}
};
class DefaultPolicy4 {};
// 将缺省值集中到
//该类将会是所有Policy Class的基类。他提供了缺省的四个Policy的类型重定义。
//因此在缺省情况下,这四个Policy将会是BreadSlicer的四个Policy。
class DefaultPolicies {
public:
typedef DefaultPolicy1 P1;
typedef DefaultPolicy2 P2;
typedef DefaultPolicy3 P3;
typedef DefaultPolicy4 P4;
};
//这里之所以给出中间类DefaultPolicyArgs,同时又让该类以虚拟继承的方式继承
//DefaultPolicies,一是为了避免后面在多重继承同一基类时而导致的二义性,同时
//也是为了方便后面其他类的继承。
class DefaultPolicyArgs : virtual public DefaultPolicies {
};
template <typename Policy>
class Policy1_is : virtual public DefaultPolicies {
public:
typedef Policy P1; // overriding typedef
};
template <typename Policy>
class Policy2_is : virtual public DefaultPolicies {
public:
typedef Policy P2; // overriding typedef
};
template <typename Policy>
class Policy3_is : virtual public DefaultPolicies {
public:
typedef Policy P3; // overriding typedef
};
template <typename Policy>
class Policy4_is : virtual public DefaultPolicies {
public:
typedef Policy P4; // overriding typedef
};
template <typename PolicySetter1 = DefaultPolicyArgs,
typename PolicySetter2 = DefaultPolicyArgs,
typename PolicySetter3 = DefaultPolicyArgs,
typename PolicySetter4 = DefaultPolicyArgs>
class BreadSlicer {
typedef PolicySelector<PolicySetter1, PolicySetter2,
PolicySetter3, PolicySetter4>
Policies;
// use Policies::P1, Policies::P2, //... to refer to the various policies.
public:
void print () {
Policies::P3::doPrint();
}
//...
};
// define a custom policy
class CustomPolicy {
public:
static void doPrint() {
std::cout << "CustomPolicy::doPrint()\n";
}
};
int main()
{
BreadSlicer<> bc1;
bc1.print();
BreadSlicer<Policy3_is<CustomPolicy> > bc2;
bc2.print();
}
待研究博客:在现代C ++中引入命名参数