Фабрика типов
От: Аноним  
Дата: 14.06.13 07:47
Оценка:
Добрый день, коллеги.
Возникла следующее не совсем здоровое желание. Хотелось бы иметь функцию (фабрику), возвращающую объекты произвольных типов, и, затем, в зависимости от типа возвращенного объекта приложение должно автоматически разруливать, какую из нескольких версий перегруженной функции (различающейся по типу аргумента) вызывать.

Псевдокод:


enum ObjectType
{
   INT,
   CHAR,
   ...
};

class Int
{
public:
   Int( string & value );
};

class Char
{
   Char( string & value );
};

??? TypeFactory( ObjectType type, string value )
{
   switch( type )
   {
    case INT:
       return( Int( value ));
    case CHAR:
       return( Char( value ));
   }
}

void foo( Int );
void foo( Char );

// Где-то в коде...
string value( "1" );
ObjectTeyp type = GetTypeOfValue( string value( "1" ));

foo( TypeFactory( type, value ));  // <-- Вот здесь должна вызваться правильная версия foo() в зависимости от типа



Такое как-то реализуемо? Что должна возвращать TypeFactory, и как объявить foo(), чтобы компилятор понимал, какую ее версию следует вызывать?
Re: Фабрика типов
От: Кодт Россия  
Дата: 14.06.13 08:06
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:

А>Добрый день, коллеги.

А>Возникла следующее не совсем здоровое желание. Хотелось бы иметь функцию (фабрику), возвращающую объекты произвольных типов, и, затем, в зависимости от типа возвращенного объекта приложение должно автоматически разруливать, какую из нескольких версий перегруженной функции (различающейся по типу аргумента) вызывать.

Здесь классический ООП подойдёт
class IFooable
{
  virtual void callFoo() = 0;
};

typedef std::shared_ptr<IFooable> PFooable;

class Int : public IFooable { ..... };
class Char : public IFooable { ..... };

PFooable TypeFactory(.....) { ..... return PFooable(new Int(...)); ..... }

void foo(PFooable obj) { ..... obj->callFoo(); ..... }

К нему можно прикрутить С++ные плюшки, такие, как автоматическую диспетчеризацию к перегруженным foo
template<class Final> class FooableImpl // CRTP
{
  virtual void callFoo() /*override*/ { foo(static_cast<Final*>(this)); }
};

void foo(PFooable obj) { obj->callFoo(); }

class Int;
void foo(Int*);

class Int : public FooableImpl<Int> { ..... };


Есть ещё пара альтернативных решений, но они слишком кудрявы, по сравнению с этим.
Перекуём баги на фичи!
Re: Фабрика типов
От: jazzer Россия Skype: enerjazzer
Дата: 14.06.13 08:06
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Добрый день, коллеги.

А>Возникла следующее не совсем здоровое желание. Хотелось бы иметь функцию (фабрику), возвращающую объекты произвольных типов, и, затем, в зависимости от типа возвращенного объекта приложение должно автоматически разруливать, какую из нескольких версий перегруженной функции (различающейся по типу аргумента) вызывать.

Boost.Variant (и его static_visitor):
http://www.boost.org/doc/libs/1_53_0/doc/html/variant.html
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: Фабрика типов
От: Кодт Россия  
Дата: 14.06.13 10:29
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Boost.Variant (и его static_visitor):


В принципе, да! Раз уж все типы перечислены в enum ObjectType, то можем себе позволить вариантный тип.

Тогда можно и ещё дальше пойти: сделать mpl-отображение этого перечисления на типы, и фабрику нагенерить автоматически.
Перекуём баги на фичи!
Re[3]: Фабрика типов
От: Warturtle  
Дата: 14.06.13 10:58
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, jazzer, Вы писали:


J>>Boost.Variant (и его static_visitor):


К>В принципе, да! Раз уж все типы перечислены в enum ObjectType, то можем себе позволить вариантный тип.


К>Тогда можно и ещё дальше пойти: сделать mpl-отображение этого перечисления на типы, и фабрику нагенерить автоматически.

Да и енум, в принципе, не нужен: список типов + make_variant_over. А если все-таки нужен, то в каком-то таком виде:
typedef boost::mpl::vector< int, char,... > ObjectTypes;
template< class T >
struct ObjectTypeIdx : boost::mpl::distance< 
    typename boost::mpl::begin< ObjectTypes >::type
    , typename boost::mpl::find< ObjectTypes, T >::type 
    > {};
...
ObjectTypeIdx< int >::value;
ObjectTypeIdx< char >::value;
...
Re[4]: Фабрика типов
От: Кодт Россия  
Дата: 14.06.13 12:51
Оценка:
Здравствуйте, Warturtle, Вы писали:

К>>Тогда можно и ещё дальше пойти: сделать mpl-отображение этого перечисления на типы, и фабрику нагенерить автоматически.

W>Да и енум, в принципе, не нужен: список типов + make_variant_over. А если все-таки нужен, то в каком-то таком виде:

То есть, получаем такую архитектуру
— примитивный тип (int,char,etc...)
— его числовой идентификатор
— его обёртка (Int,Char,etc...), которую, скорее всего, можно нагенерить из шаблона
— вариантный тип — упаковка обёрток
— фабрика обёрток по номеру
— перегруженная для обёрток функция foo, а скорее всего, её тоже можно нагенерить из шаблона
И всё это развёртывается из списка примитивных типов!
Перекуём баги на фичи!
Re[5]: Фабрика типов
От: jazzer Россия Skype: enerjazzer
Дата: 15.06.13 03:15
Оценка:
Здравствуйте, Кодт, Вы писали:

К>И всё это развёртывается из списка примитивных типов!


Ну да, так и делается обычно в наших MPL-ях, чего тут такого
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[6]: Фабрика типов
От: Кодт Россия  
Дата: 15.06.13 13:22
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Ну да, так и делается обычно в наших MPL-ях, чего тут такого

J>

Да всё неплохо, кроме рокет-саенса или вуду-мэджика.
Больше того, не составит труда сделать всё то же самое на препроцессоре, — но это будет больше вуду, чем рокет.
Перекуём баги на фичи!
Re: Фабрика типов
От: romankr  
Дата: 16.06.13 21:03
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Добрый день, коллеги.

А>Возникла следующее не совсем здоровое желание. Хотелось бы иметь функцию (фабрику), возвращающую объекты произвольных типов, и, затем, в зависимости от типа возвращенного объекта приложение должно автоматически разруливать, какую из нескольких версий перегруженной функции (различающейся по типу аргумента) вызывать.

Гуглите кейворд dynamic dispatch, можно найти достаточно много вариантов В дополнение к уже озвученному (с использованием виртуальных функций и вариантного типа), напомню, что есть RTTI, typeid() и класс type_info.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.