带有不可复制类的模板类型推导

Eva*_*ran 2 c++ templates

假设我有一个autolocker类,看起来像这样:

template <T>
class autolocker {
public:
    autolocker(T *l) : lock(l) {
        lock->lock();
    }

    ~autolocker() {
        lock->unlock();
    }
private:
    autolocker(const autolocker&);
    autolocker& operator=(const autolocker&);
private:
    T *lock;
};
Run Code Online (Sandbox Code Playgroud)

显然,目标是能够将此autolocker与任何具有锁定/解锁方法的东西一起使用,而无需借助虚拟功能.

目前,它很简单,使用如下:

autolocker<some_lock_t> lock(&my_lock); // my_lock is of type "some_lock_t"
Run Code Online (Sandbox Code Playgroud)

但这样做是违法的:

autolocker lock(&my_lock); // this would be ideal
Run Code Online (Sandbox Code Playgroud)

反正有没有得到模板类型演绎与此相关(保持在我的autolocker是不可复制的).或者只是指定类型最简单?

Joh*_*itb 5

是的,你可以使用范围保护技术

struct autolocker_base {
    autolocker_base() { } 
protected:
    // ensure users can't copy-as it
    autolocker_base(autolocker_base const&) 
    { }

    autolocker_base &operator=(autolocker_base const&)
    { return *this; }
};

template <T>
class autolocker : public autolocker_base {
public:
    autolocker(T *l) : lock(l) {
        lock->lock();
    }

    autolocker(const autolocker& o)
      :autolocker_base(o), lock(o.lock)
    { o.lock = 0; }

    ~autolocker() {
        if(lock)
          lock->unlock();
    }

private:
    autolocker& operator=(const autolocker&);

private:
    mutable T *lock;
};
Run Code Online (Sandbox Code Playgroud)

然后编写一个创建自动锁定器的函数

template<typename T>
autolocker<T> makelocker(T *l) {
  return autolocker<T>(l);
}

typedef autolocker_base const& autolocker_t;
Run Code Online (Sandbox Code Playgroud)

然后你可以这样写:

autolocker_t lock = makelocker(&my_lock);
Run Code Online (Sandbox Code Playgroud)

一旦const引用超出范围,就会调用析构函数.它不需要是虚拟的.至少GCC 很好地优化了这一点.

遗憾的是,这意味着您必须使您的储物柜对象可以复制,因为您需要从制造商函数返回它.但旧对象不会尝试解锁两次,因为它的指针在被复制时设置为0,所以它是安全的.