powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Статическая фабрика обьектов
25 сообщений из 25, страница 1 из 1
Статическая фабрика обьектов
    #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
Статическая фабрика обьектов
    #38189375
?
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
?
Гость
Katamaran1987Возможно ли сделать фабрику которуя я на этапе компиляции забиваю типами, потом когда программа выполняется создать этот тип допустим по строке, по енуму неважно, но чтоб не возращать void* а конкретный тип.
...
пожалуйста не предлагайте вариант с полиморфизмом.
В С++ - невозможно.
Katamaran1987 Вообще классы ABC в идеале должны использовать статичекий полиморфизм(crtp pattern) но чтоб фабрика возратила base<type> find_and_create().Может возможен вызов функции из void * чтото вроде ret->&A::foo но это не валидный код.Какие есть варинаты решение такой задачи?Чтобы вызвать foo(), надо иметь базовый класс, в котором определен метод foo(). А вы не хотите. Тогда вам нужен язык с динамической типизацией.
...
Рейтинг: 0 / 0
Статическая фабрика обьектов
    #38189838
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
?Katamaran1987Возможно ли сделать фабрику которуя я на этапе компиляции забиваю типами, потом когда программа выполняется создать этот тип допустим по строке, по енуму неважно, но чтоб не возращать void* а конкретный тип.
...
пожалуйста не предлагайте вариант с полиморфизмом.

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


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

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


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

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

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

Можно это же сделать одним методом,
шаблонным.
Толку только 0.
...
Рейтинг: 0 / 0
Статическая фабрика обьектов
    #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
Статическая фабрика обьектов
    #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
Статическая фабрика обьектов
    #38191227
sherzod_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Katamaran1987,

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

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

Другое дело, что это в принципе проблема вашего дизайна, что одна фабрика создает объекты совершенно различных классов без общего предка из-за чего вы не можете использовать полиморфизм.
...
Рейтинг: 0 / 0
Статическая фабрика обьектов
    #38191608
Katamaran1987задача то какая?Katamaran1987, задача то какая?
Нормально и полно сформулируйте парой предложений.Все очень просто есть фабрика на этапе компиляции я забиваю ее типами, во время выполнения приходят строки которые закидываются в метод фабрики и создаются обьекты по этой строке, но сейчас я смог возратить void* от созданного обьекта а хотелось бы конкретный тип.
Все до единого типы известны уже на этапе компиляции. Вариант только полиморфизм. Т.е. конкретно в такой постановке задача не имеет решения.
А вам нужно boost::any или boost::variant<>
...
Рейтинг: 0 / 0
Статическая фабрика обьектов
    #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
Статическая фабрика обьектов
    #38191719
Katamaran1987Предок есть вот такие классы:
Вы знаете что такое предок? Это тип от которого наследуются. А здесь нет наследования.
...
Рейтинг: 0 / 0
Статическая фабрика обьектов
    #38191730
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я беру свои слова обратно, дизайн тут не причем.
Дизайна тут вообще нет
...
Рейтинг: 0 / 0
Статическая фабрика обьектов
    #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
Статическая фабрика обьектов
    #38191772
Inkelyad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Объясните глупому новичку, почему не
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
main()
{
    A a;
    B b;
    a.foo();
    b.foo();
}


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

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


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