demonstrate 的 blog

daily blog

C++ 的 idioms(六)

leave a comment »

coercion by member template

这是写智能指针必备的 pattern,前面也讨论过这种现象:

template <class T>
class ptr {
  T* p ;
public:
  template<class U> ptr<T>&
  operator= (const ptr<U>& that) {
    p = that -> p ;
  }
} ;

如果类 A 被 B 继承,B* 可以转换 A*,但是 ptr<B> 却无法自动转换成 ptr<A>,因为不具有继承关系。这样就需要上面这种 pattern。其实这种 pattern 相当于延后了类型检查,直到函数里面,很多 functor 的 generator,如 boost.bind 也是利用的这种技术。

clear and minimize

这是清空 STL 容器一种常用的策略,

std::vector<int> v ;
// doing lots of op to v to boost the size
std::vector<int> ().swap (v) ;
// cleared and minimized

不知道这个跟 clear() 或者 shrink_to_fit() 区别在哪里?

Computational Constructor

这个可能是个比较 boring 的 idiom,为了让编译器能够更好的做 RVO 或者 NRVO(即 return value optimization 与 named return-value optimization),就将很多操作放在 constructor 里面,而不是放在一些成员函数里面,然后通过成员函数修改 object 之后返回。

const auto ptr

如果想弄一个具有绝对所有权的智能指针,咋一想 const auto_ptr<T> 是不是就 work 了?因为 operator= 会修改输入的 auto_ptr,这意味着输入的是 non-const auto_ptr<T> 的引用。这样如果声明了一个 const auto_ptr<T>,那么不就不能通过 operator= 转移它的属主权利了么?

问题是这个 pattern 不能够被复用。比如在某个类里面嵌入这样一个成员,默认的 copy constructor 会调用 auto_ptr 的对应版本,这样实例化之后就出现了矛盾,因为输入的是 const 版本,但是 auto_ptr 要求是 non-const。这个问题在 gcc 4.6 里面可以被重现

#include <memory>

struct foo {
  const std::auto_ptr<int> p ;

  foo(int* i) : p(i) {}
} ;

int
main (int, char**) {
  foo bar (new int (1)) ;
  foo rab (bar) ;

  return 0 ;
}

但在 4.2 或者 4.4 都不行。说明编译器检查有时候也不是太严格。解决方案一个是使用 boost::scoped_ptr,

concrete data type

这个 idiom 是通过修改 virtual destructor 的位置(在 public 还是 protected)来表达希望怎么用这个类:如果是 public,我们就可以显式调用它(使用它的指针或者引用或者对象本身)delete;如果是 protected,我们就只能通过其父类的指针、引用来做这个事情:

class base {
public:
  virtual ~base () {}
} ;
class derived : public base {
protected:
  virtual ~derived () ;
} ;

// when u use it
base* ptr = new derived ;
delete ptr ;

// but this will cause compilation error
derived a ;

这样看起来就是鼓励仅仅使用指针将对象放在 heap 里。那么如果希望变量仅能存在 stack 而不能放在 heap 里面,也可以将对应的 operator new 放进这种位置,这样就只能在一个 scope 里面使用了。

类似的一种想法就是某些对象不希望用户调用构造函数产生,而希望使用对应的 factory,可以将构造函数(甚至析构)都放在 private 段,某个 factory 作为 friend 专门来调用产生对象(或者释放)。

——————
And the king of Sodom said to Abram, Give me the persons, and take the goods to yourself.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.