Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Статическая фабрика обьектов / 25 сообщений из 25, страница 1 из 1
19.03.2013, 11:07
    #38189190
Katamaran1987
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
Возможно ли сделать фабрику которуя я на этапе компиляции забиваю типами, потом когда программа выполняется создать этот тип допустим по строке, по енуму неважно, но чтоб не возращать void* а конкретный тип.Вот код который у меня сейчас получился:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
namespace detail
{
    template<size_t i,typename... types>
    struct get_variadic_type;
    template<size_t i,typename cur_t,typename... types>
    struct get_variadic_type<i,cur_t,types...>
    {
        typedef typename get_variadic_type<i-1,types...>::current_type current_type;
    };
    template<typename cur_t,typename... types>
    struct get_variadic_type<0,cur_t,types...>
    {
        typedef cur_t current_type;
    };
}


template<size_t i,typename... types>
struct create_item_impl
{
    typedef typename detail::get_variadic_type<i,types...>::current_type type;
    template<typename... targs_t>
    static void* create(const char *str,targs_t ...args)
    {
        if(strcmp(type::name,str)==0)
        {
            return new type(args...);
        }
        else
        {
            return create_item_impl<i-1,types...>::create(str,args...);
        }
    }
};
template<typename... types>
struct create_item_impl<0,types...>
{
    typedef typename detail::get_variadic_type<0,types...>::current_type type;
    template<typename... targs_t>
    static void* create(const char *str,targs_t ...args)
    {
        if(strcmp(type::name,str)==0)
        {
            return  new type(args...);
        }
        else
        {
            return nullptr;
        }
    }
};

template<typename... types>
struct create_item
{
    enum {size = sizeof...(types)-1};
    template<typename... targs_t>
    static void* create(const char *str,targs_t ...args)
    {
        return create_item_impl<size,types...>::create(str,args...);
    }
};
template<typename type_t>
struct factory_item
{
    static constexpr const char * name = "unknown";
};
struct A:public factory_item<A>
{
    static constexpr const char * name = "A";
    A(const std::string &val)
    {

    }
    void foo(){}
};
struct B:public factory_item<B>
{
    static constexpr const char * name = "B";
    B(const std::string &val)
    {

    }
    void foo(){}
};
struct C:public factory_item<C>
{
    static constexpr const char * name = "C";
    C(const std::string &val)
    {

    }
    void foo(){}
};

template<typename... types>
struct static_factory
{
    template<typename... targs_t>
    void* find_and_create(const char * val,targs_t ...args)
    {
        return create_item<types...>::create(val,args...);
    }
};


int main(int argc, char* argv[])
{
   static_factory<A,C,B > fac;
   void *ret= fac.find_and_create("A","S"); // надо бы вызвать foo
  return 0;
}

пожалуйста не предлагайте вариант с полиморфизмом. Вообще классы ABC в идеале должны использовать статичекий полиморфизм(crtp pattern) но чтоб фабрика возратила base<type> find_and_create().Может возможен вызов функции из void * чтото вроде ret->&A::foo но это не валидный код.Какие есть варинаты решение такой задачи?
...
Рейтинг: 0 / 0
19.03.2013, 12:12
    #38189375
?
?
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
Katamaran1987Возможно ли сделать фабрику которуя я на этапе компиляции забиваю типами, потом когда программа выполняется создать этот тип допустим по строке, по енуму неважно, но чтоб не возращать void* а конкретный тип.
...
пожалуйста не предлагайте вариант с полиморфизмом.
В С++ - невозможно.
Katamaran1987 Вообще классы ABC в идеале должны использовать статичекий полиморфизм(crtp pattern) но чтоб фабрика возратила base<type> find_and_create().Может возможен вызов функции из void * чтото вроде ret->&A::foo но это не валидный код.Какие есть варинаты решение такой задачи?Чтобы вызвать foo(), надо иметь базовый класс, в котором определен метод foo(). А вы не хотите. Тогда вам нужен язык с динамической типизацией.
...
Рейтинг: 0 / 0
19.03.2013, 14:52
    #38189838
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
?Katamaran1987Возможно ли сделать фабрику которуя я на этапе компиляции забиваю типами, потом когда программа выполняется создать этот тип допустим по строке, по енуму неважно, но чтоб не возращать void* а конкретный тип.
...
пожалуйста не предлагайте вариант с полиморфизмом.

В С++ - невозможно.


Почему невозможно ?
Забить в методы создания конкретных типов конкретные сигнатуры (типы возврата) и всё.
Можно использовать шаблоны, с помощью их нагенерировать такие "фабрики".
Только это как-то уже не фабрика вовсе. Что там от фабрики остаётся?
Скорее это похоже на фабричный метод.
...
Рейтинг: 0 / 0
19.03.2013, 15:34
    #38189916
Katamaran1987
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
MasterZiv?пропущено...

В С++ - невозможно.


Почему невозможно ?
Забить в методы создания конкретных типов конкретные сигнатуры (типы возврата) и всё.
Можно использовать шаблоны, с помощью их нагенерировать такие "фабрики".
Только это как-то уже не фабрика вовсе. Что там от фабрики остаётся?
Скорее это похоже на фабричный метод.Я тоже об этом думал но это все надо сделать в одном методе, в котором я передаю и аргументы для создания класса и сигнатуры функций которые надо вызвать, да еще их параметры сума сойдешь потом это сопровождать, да и разгребсти что для чего.И сразу как создал надо будет удалять, а тут еще и пул созданных обектов нужен, тяжелый вариант.
...
Рейтинг: 0 / 0
19.03.2013, 15:53
    #38189963
Katamaran1987
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
MasterZivЗабить в методы создания конкретных типов конкретные сигнатуры (типы возврата) и всё. Никак не могу понять что имелось ввиду.Можно пример схематично.
...
Рейтинг: 0 / 0
19.03.2013, 17:44
    #38190283
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
Katamaran1987,

Блин какие примеры?

20 методов,
Создать то, возвращает то,
Создать это, возвращает это,
Создать хрень 23, возвращает хрень 23
И так далее.

Можно это же сделать одним методом,
шаблонным.
Толку только 0.
...
Рейтинг: 0 / 0
19.03.2013, 19:34
    #38190447
Легко
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
Легко:
http://ideone.com/h64ZX3] http://ideone.com/h64ZX3

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
#include<memory>
#include<iostream>
#include<type_traits>
using namespace std;



template<typename T, typename... types>
struct T_fabric
{
    enum {size = sizeof...(types)};
    T_fabric<types...> fabric;

    template < size_t N,
               class Tc = typename enable_if<size == N, T>::type>
    shared_ptr<Tc> create() { return make_shared<Tc>(); }
    
    template < size_t N,
               class Tc = typename enable_if<size != N, T>::type>
    auto create() -> decltype(fabric.create<N>()) { return fabric.create<N>(); }    
};

template<typename T>
struct T_fabric<T> {
    template < size_t N,
           class = typename enable_if<0 == N>::type>
    shared_ptr<T> create() { return make_shared<T>(); }
};


int main() {
    T_fabric<double, float, int> fabric;
    
    auto v0 = *(fabric.create<0>());
    auto v1 = *(fabric.create<1>());
    auto v2 = *(fabric.create<2>());
    
    std::cout << "v0: " << typeid(v0).name() << '\n';
    std::cout << "v1: " << typeid(v1).name() << '\n';
    std::cout << "v2: " << typeid(v2).name() << '\n';

    
    return 0;
}



выводv0: i
v1: f
v2: d

Вопрос только в том, что у вас не четко сформулирована задача.
...
Рейтинг: 0 / 0
20.03.2013, 10:14
    #38190971
Katamaran1987
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
Легко... Это не является решением моего вопроса, еслиб мне надо был тип на этапе компиляции нафига мне такая фабрика,я сразу предаставлю тип?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
template<typename... Types>
struct Foo
{
    // Forward declaration
    template<int id, typename... Types_>
    struct X;
 
    // Declaration
    template<int id, typename First, typename... Types_>
    struct X<id, First, Types_...>: X<id - 1, Types_...>
    {
    };
 
    // Specialized
    template<typename First, typename... Types_>
    struct X<0, First, Types_...>
    {
        typedef First DataType;
    };
 
    // Preferable (template aliases) way but we have to wait for GCC 4.7
    // template<int id>
    // using DataType = X<id, Types...>::DataType;
 
    template<int id>
    struct Y
    {
        typedef typename X<id, Types...>::DataType DataType;
    };
};
 
int main(int, char**)
{
    typedef Foo<double, int, std::string> MyFoo;
    MyFoo::Y<0>::DataType a(1.23);
    MyFoo::Y<1>::DataType b(123);
    MyFoo::Y<2>::DataType c("Hello");
 
    std::cout << a << " " << b << " " << c << std::endl;
}

Вот намного проще и понятней, также вместе enable_if можно и нужно использовать disable_if если условие одно и тоже а нужна другая перегрузка. Проблема что тип нуже на этапе выполнения, а это не возможно получить потомучто C++ строго типизированный и выход или использовать virtual или все действия выполнять сразу как создал обьект, в тойже функции и в конце удалять обьект, или создавать целую кучу функций.
...
Рейтинг: 0 / 0
20.03.2013, 12:35
    #38191227
sherzod_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
Katamaran1987,

нужно раз и навсегда понять, что так как заранее неизвестно какое значение будет передано функции в данной строке кода (в вашем случае фабричному методу), то неизбежно нужен механизм диспатчинга, какой-нибудь switch-case, hash-таблица, или любой другой, который основываясь на переданном значении сделает соответствующие этому значению действия в райнтайме. В C++ есть удобный быстрый надежный встроенный механизм для этого - виртуальные функции-члены. Поэтому или изобретайте их заново долго совершенствуя и исправляя баги, или просто используйте их .

PS: Зачем в стопицотый раз заниматься безнадежным аутотренингом, что возможно есть что-то, что волшебным образом срастит рантайм с компайл-тайм?
...
Рейтинг: 0 / 0
20.03.2013, 12:38
    #38191233
Katamaran1987
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
sherzod_Katamaran1987,
PS: Зачем в стопицотый раз заниматься безнадежным аутотренингом, что возможно есть что-то, что волшебным образом срастит рантайм с компайл-тайм? http://cpptruths.blogspot.com/2011/07/want-speed-use-constexpr-meta.html constexpr почти сращивает.
...
Рейтинг: 0 / 0
20.03.2013, 12:44
    #38191242
sherzod_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
Katamaran1987sherzod_Katamaran1987,
PS: Зачем в стопицотый раз заниматься безнадежным аутотренингом, что возможно есть что-то, что волшебным образом срастит рантайм с компайл-тайм? http://cpptruths.blogspot.com/2011/07/want-speed-use-constexpr-meta.html constexpr почти сращивает. Что означает почти? Мне известно лишь одно взаимодействие между кт и рт и это "перенос". Причем несмотря на всю монструозность метапрограммирования на С++, оно основано на очень простом принципе, если все известно на этапе компиляции, то и вычислить можно на этапе компиляции, если нет - только рантайм. И уже все равно как глубоко зарыты известные данные (в функции, выражениях, перечислениях вложенных в классы вложенных в классы и тд). Какие тут могут быть почти?
...
Рейтинг: 0 / 0
20.03.2013, 14:34
    #38191453
Katamaran1987
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
sherzod_... Почти что функции конст экспрешн могут вычислить значение как в рантайме так и во время компиляции.
...
Рейтинг: 0 / 0
20.03.2013, 15:18
    #38191542
Статическая фабрика обьектов
Katamaran1987, задача то какая?
Нормально и полно сформулируйте парой предложений.
...
Рейтинг: 0 / 0
20.03.2013, 15:28
    #38191560
Katamaran1987
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
задача то какая?Katamaran1987, задача то какая?
Нормально и полно сформулируйте парой предложений.Все очень просто есть фабрика на этапе компиляции я забиваю ее типами, во время выполнения приходят строки которые закидываются в метод фабрики и создаются обьекты по этой строке, но сейчас я смог возратить void* от созданного обьекта а хотелось бы конкретный тип.
...
Рейтинг: 0 / 0
20.03.2013, 15:48
    #38191600
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
Katamaran1987Все очень просто есть фабрика на этапе компиляции я забиваю ее типами, во время выполнения приходят строки которые закидываются в метод фабрики и создаются обьекты по этой строке , но сейчас я смог возратить void* от созданного обьекта а хотелось бы конкретный тип.
Чтобы был конкретный тип, он должен быть известен при компиляции, а у вас он становится известен при выполнении.
Так что забудьте.

Другое дело, что это в принципе проблема вашего дизайна, что одна фабрика создает объекты совершенно различных классов без общего предка из-за чего вы не можете использовать полиморфизм.
...
Рейтинг: 0 / 0
20.03.2013, 15:51
    #38191608
Статическая фабрика обьектов
Katamaran1987задача то какая?Katamaran1987, задача то какая?
Нормально и полно сформулируйте парой предложений.Все очень просто есть фабрика на этапе компиляции я забиваю ее типами, во время выполнения приходят строки которые закидываются в метод фабрики и создаются обьекты по этой строке, но сейчас я смог возратить void* от созданного обьекта а хотелось бы конкретный тип.
Все до единого типы известны уже на этапе компиляции. Вариант только полиморфизм. Т.е. конкретно в такой постановке задача не имеет решения.
А вам нужно boost::any или boost::variant<>
...
Рейтинг: 0 / 0
20.03.2013, 16:30
    #38191682
Katamaran1987
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
Anatoly MoskovskyKatamaran1987Все очень просто есть фабрика на этапе компиляции я забиваю ее типами, во время выполнения приходят строки которые закидываются в метод фабрики и создаются обьекты по этой строке , но сейчас я смог возратить void* от созданного обьекта а хотелось бы конкретный тип.
Чтобы был конкретный тип, он должен быть известен при компиляции, а у вас он становится известен при выполнении.
Так что забудьте.

Другое дело, что это в принципе проблема вашего дизайна, что одна фабрика создает объекты совершенно различных классов без общего предка из-за чего вы не можете использовать полиморфизм.

Предок есть вот такие классы:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
template<typename impl>
struct base
{
void foo()
{
  impl_.foo();
}
  impl impl_;
};
struct A
{
void foo(){}
}
struct B
{
void foo(){}
}
template<typename type_t>
void do_foo(base<type_t> &imp)
{
imp.foo();
}
main()
{
base<A> a;
base<B> b;
do_foo(a);
do_foo(b);
}
...
Рейтинг: 0 / 0
20.03.2013, 16:41
    #38191719
Статическая фабрика обьектов
Katamaran1987Предок есть вот такие классы:
Вы знаете что такое предок? Это тип от которого наследуются. А здесь нет наследования.
...
Рейтинг: 0 / 0
20.03.2013, 16:47
    #38191730
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
Я беру свои слова обратно, дизайн тут не причем.
Дизайна тут вообще нет
...
Рейтинг: 0 / 0
20.03.2013, 16:49
    #38191741
Katamaran1987
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
наследуютсяKatamaran1987Предок есть вот такие классы:
Вы знаете что такое предок? Это тип от которого наследуются. А здесь нет наследования.Чушь, это CRTP патерн только я не наследую а делегирую.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
template<typename derived_t>
struct base 
{
void foo()
{
  return static_cast<derived*>(this)->foo();
}
};
struct A : public base<A>
{
void foo(){}
}
struct B: public base<B>
{
void foo(){}
}
template<typename type_t>
void do_foo(base<type_t> &imp)
{
imp.foo();
}
main()
{
A a;
B b;
do_foo(a);
do_foo(b);
}

Специально для вас.
...
Рейтинг: 0 / 0
20.03.2013, 17:02
    #38191772
Inkelyad
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
Объясните глупому новичку, почему не
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
main()
{
    A a;
    B b;
    a.foo();
    b.foo();
}


Для каких целей do_foo понадобилась?
...
Рейтинг: 0 / 0
20.03.2013, 17:12
    #38191790
Katamaran1987
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
InkelyadОбъясните глупому новичку, почему не
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
main()
{
    A a;
    B b;
    a.foo();
    b.foo();
}


Для каких целей do_foo понадобилась?Потому что я привел обычный пример, в C++ есть 2 полиморфизма один динамический а второй статический с помощью вот таких do_foo мы получаем полиморфное поведение обьектов, что заменяет virtual и не нужна никакая таблица вирт функций, ни деструкторы виртупальные, нинакладные расходы на вызов виртуальной функции, и экономия на размере класса изза указателя на таблицу. Вот сколько плюсов ребята, с виртуалом любой дурак сделает.Может моя задача в данном топике так просто не решится но паттерн достойный изучения.На нем весь ATL/WTL построен.
...
Рейтинг: 0 / 0
20.03.2013, 17:18
    #38191808
Inkelyad
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
Katamaran1987Потому что я привел обычный пример, в C++ есть 2 полиморфизма один динамический а второй статический с помощью вот таких do_foo мы получаем полиморфное поведение обьектов, что заменяет virtual и не нужна никакая таблица вирт функций, ни деструкторы виртупальные, нинакладные расходы на вызов виртуальной функции, и экономия на размере класса изза указателя на таблицу.
Не понимаю. foo не была объявлена виртуальной же. классы А и B вообще могут независимыми классами быть. И все отлично вызовется.
...
Рейтинг: 0 / 0
20.03.2013, 17:23
    #38191820
Katamaran1987
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
Inkelyad...Виртуальность в данном случаи не нужна, все методы вызываются в соответсвии с типом, все связывание происходит на этапе компиляции.
Код: plaintext
1.
2.
template<typename derived_t>
struct base 

это базовой класс и в do_foo я принимаю базовый класс, но так как тип известен на этапе компиляции то в функция вызовет тот метод который нужен. do_foo скорее всего будет соптимизирована компилятором,но я в итоге получил полиморфное поведение.
...
Рейтинг: 0 / 0
20.03.2013, 17:25
    #38191824
Katamaran1987
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статическая фабрика обьектов
Inkelyad...do_foo не пропустит класс у которого будет просто метод foo но он не был унаследован от базового template<typename derived_t>base; ты получишь ошибку компиляции.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Статическая фабрика обьектов / 25 сообщений из 25, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]