我想为模板化的 RAII 类编写一个对象生成器——基本上是一个函数模板,用于使用参数的类型推导构造一个对象,因此不必明确指定类型。
我预见的问题是,为我处理类型推导的辅助函数将按值返回对象,这将 (**) 导致在复制时过早调用 RAII 析构函数。也许 C++0x 移动语义会有所帮助,但这对我来说不是一个选择。
有人以前见过这个问题并有好的解决方案吗?
这就是我所拥有的:
template<typename T, typename U, typename V>
class FooAdder
{
private:
typedef OtherThing<T, U, V> Thing;
Thing &thing_;
int a_;
// many other members
public:
FooAdder(Thing &thing, int a);
~FooAdder();
FooAdder &foo(T t, U u);
FooAdder &bar(V v);
};
要点是它OtherThing
有一个可怕的界面,并且FooAdder
应该使它更易于使用。预期用途大致是这样的:
FooAdder(myThing, 2)
.foo(3, 4)
.foo(5, 6)
.bar(7)
.foo(8, 9);
构造FooAdder
函数初始化一些内部数据结构。foo
和bar
方法填充这些数据结构。~FooAdder
dtor 将事情包装起来并调用 on 方法thing_
,处理所有的麻烦。
FooAdder
如果不是模板,那会很好用。但既然是这样,我需要把类型放进去,更像这样:
FooAdder<Abc, Def, Ghi>(myThing, 2) ...
这很烦人,因为类型可以基于myThing
. 所以我更愿意创建一个模板化的对象生成器,类似于std::make_pair
,它将为我进行类型推导。像这样的东西:
template<typename T, typename U, typename V>
FooAdder<T, U, V>
AddFoo(OtherThing<T, U, V> &thing, int a)
{
return FooAdder<T, U, V>(thing, a);
}
这似乎有问题:因为它按值返回,堆栈临时对象将 (**) 被破坏,这将导致 RAII dtor 过早运行。
** - 如果未实施 RVO。大多数编译器都这样做,但这不是必需的,可以在 gcc 中使用-fno-elide-constructors
.