设计中的C ++特性习语

时间:2018-07-06 02:19:22

标签: c++ oop traits

考虑定义

class A1{/*something*/};

以下两个选项

  

1)使用助手

struct A1_helper{
typedef A1 underlying; //let A1_helper user direct access to A1
//whatever else necessary to work with A1...
};


template<typename A_helper>
class B
{
//use A_helper
}; 


B<A1_helper> b;
     

2)使用特征

template<A>
struct A_traits{
//whatever necessary to work with A...
};



template<typename A>
class B2
{
    //use A_traits<A>
};

B<A> b;

我的问题是:除了特征的现代性,这两种设计之间是否存在本质区别?有什么可以用一个做的但不能用另一个做的吗?也许是一个更好的问题,什么时候您称其为特质?

1 个答案:

答案 0 :(得分:1)

这两种方法的含义存在显着差异。

方法1允许用户自定义每个站点如何执行A型处理。

struct A_helper_1 {
   static int to_int(A a) { return 1; }
};

struct A_helper_2 {
   static int to_int(A a) { return 2; }
};

A a;
B<A_helper_1> b1;
b1.printA(a);
B<A_helper_2> b2;
b2.printA(a);

使用方法2时,A类只有一个真实的行为。

template<>
struct Helper<A> {
  static int to_int(A a) { return 1; }
};

A a;
B<A> b;
b.printA(a);

方法2-如果您想要一种新的行为,则需要包装您的课程

struct A2 : public A {/* ... all the constructors etc. ... */ }

template<>
struct Helper<A2> {
   static int to_int(A2 a) { return 1; }
}

B<A> b1;
B<A2> b2;
A a;
b1.printA(a);
// Only OK if you have a conversion operator in A2 - but will create a temp copy!
b2.printA(a); 
A2 a2;
b1.printA(a2); // OK but might copy a slice depending on call signature
b2.printA(a2);

因此,IMO使用方法1暗示底层代码是可扩展的,而方法2则不是,因为1的扩展容易得多,但其实例化却更加冗长(B<A_helper>B<A>)。

值得注意的是,使用方法1可以解决一些冗长的问题,方法是执行以下附加步骤,并使用C代替B

template<typename T>
struct default_helper;

template<typename T>
using C = B<default_helper<T>>

template<>
struct default_helper<A> {
   static int to_int(A a) { return 1; }
}

A a;
C<A> c;
c.printA(a);