Я хотел бы написать генератор объектов для шаблонного класса 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 оборачивает вещи и вызывает метод на 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);
}
Это кажется проблематичным: поскольку он возвращается по значению, временный объект стека будет (**) разрушен, что приведет к преждевременной работе dtor-модуля RAII.
** - если RVO не реализовано. Большинство компиляторов делают, но это не обязательно, и их можно отключить в gcc, используя -fno-elide-constructors
.