Очевидно, что вы не можете сойти с autolocker
как шаблон, потому что вы хотите использовать его как тип, и шаблоны должны быть созданы для получения типов.
Но стирание типа может использоваться для того, что вы хотите. Вы превращаете шаблон класса в класс, а его конструктор в шаблон члена. Но тогда вам придется динамически выделять внутренний объект реализации.
Лучше сохранить указатель на функцию, которая выполняет разблокировку, и пусть эта функция будет экземпляром шаблона, выбранного шаблонизированным конструктором. Что-то вроде этого:
// Comeau compiles this, but I haven't tested it.
class autolocker {
public:
template< typename T >
autolocker(T *l) : lock_(l), unlock_(&unlock<T>) { l->lock(); }
~autolocker() { unlock_(lock_); }
private:
autolocker(const autolocker&);
autolocker& operator=(const autolocker&);
private:
typedef void (*unlocker_func_)(void*);
void *lock_;
unlocker_func_ unlock_;
template <typename T>
static void unlock(void* lock) { ((T*)lock)->unlock(); }
};
На самом деле я не пробовал этого, и синтаксис может быть неправильным (я не уверен, как получить адрес конкретного экземпляра шаблона функции), но я думаю, что это должно быть выполнимо в принципе. Может быть, кто-то приходит и исправляет то, что я ошибся.
Мне это нравится намного больше, чем охрана прицела, которая по какой-то причине мне вообще никогда не нравилась.