Opened 6 years ago

Closed 6 years ago

#278 closed ожидается проверка (задача сдана)

HA4: function

Reported by: goncharov.artem Owned by: rutsky,grabovoy.philipp
Priority: проверка Milestone: ha4-deadline
Component: HA#4 function Version: 1.0
Keywords: Cc:

Description

Посмотрите, пожалуйста.

Change History (13)

comment:1 Changed 6 years ago by cpptester

Type: ожидается проверкаожидаются исправления

Tested revision 599 by goncharov.artem.

Smoke tests

test

stage

result

info

log

run_function_smoke_test.cpp

FAILURE

run_function_smoke_test-gcc62.log

Common header used in some tests: common.h

comment:2 Changed 6 years ago by cpptester

Tested revision 689 by goncharov.artem.

Smoke tests

test

stage

result

info

log

run_function_smoke_test.cpp

SUCCESS
FAILURE

exit code 139

run_function_smoke_test-run.log

Common header used in some tests: common.h

comment:3 Changed 6 years ago by cpptester

Tested revision 689 by goncharov.artem.

Main tests

test

stage

result

info

log

run_free_function.cpp

SUCCESS
FAILURE

exit code 139

run_free_function-run.log

Common header used in some tests: common.h

comment:4 Changed 6 years ago by cpptester

Tested revision 689 by goncharov.artem.

Main tests

test

stage

result

info

log

run_free_function.cpp

SUCCESS
FAILURE

exit code 139

run_free_function-run.log

run_functor_desctructor.cpp

SUCCESS
FAILURE

exit code 139

run_functor_desctructor-run.log

Common header used in some tests: common.h

comment:5 Changed 6 years ago by cpptester

Tested revision 689 by goncharov.artem.

Main tests

test

stage

result

info

log

run_free_function.cpp

SUCCESS
FAILURE

exit code 139

run_free_function-run.log

run_functor_desctructor.cpp

SUCCESS
FAILURE

exit code 139

run_functor_desctructor-run.log

Common header used in some tests: common.h

comment:6 Changed 6 years ago by cpptester

Tested revision 689 by goncharov.artem.

Main tests

test

stage

result

info

log

run_free_function.cpp

SUCCESS
FAILURE

exit code 139

run_free_function-run.log

Common header used in some tests: common.h

comment:7 Changed 6 years ago by cpptester

Tested revision 714 by goncharov.artem.

All tests passed. Good job!

comment:8 Changed 6 years ago by goncharov.artem

Type: ожидаются исправленияожидается проверка

comment:9 Changed 6 years ago by Филипп

Milestone: ha4-milestone2ha4-deadline
Type: ожидается проверкаожидаются исправления

Привет!

  1. В function_pointer_cast достаточно reinterpret_cast
  2. Почему в этом методе вызывается так параметризованный create? Я сходу не составил хороший пример (компилятор все соптимизировал), это же может вести к вложенности function друг в друга.
    function(function<ResT2(ArgsT2...)> const &other) {
        details::DataManager<function<ResT2(ArgsT2...)>>::create(container, other);
        ....
    
  3. (Чисто стилистическое) странная получается роль у DataManager, не совсем соответствует неймингу: он скорее походит на какой-то MethodsPreparator :)

comment:10 Changed 6 years ago by cpptester

Tested revision 820 by goncharov.artem.

All tests passed. Good job!

comment:11 Changed 6 years ago by goncharov.artem

Здравствуйте!

Первое и третье поправил. На счет второго: не знаю, как от этого избавиться, ведь если в конструктор передан function с другой сигнатурой, то никак нельзя получить информацию о типе объекта-функтора, который лежит внутри. А без этого не получится создать требуемые методы (invoker, deleter, copier). Поэтому для такого случая вызывается обычный конструктор для объекта-функтора и в результате получается вложенность. На сколько я понял, в стандартной библиотеке используется такой же подход, и тоже присутствует вложенность. От этого возможно избавиться?

comment:12 Changed 6 years ago by goncharov.artem

Type: ожидаются исправленияожидается проверка

comment:13 Changed 6 years ago by Филипп

Resolution: задача сдана
Status: newclosed

Да, сорри, я при первичном просмотре проигнорил другие типы аргументов. С ними сохранения всего функтора не избежать.

Замечание в общем по решению:

Работу с copier, invoker, deleter хорошо было бы инкапсулировать в "интерфейс" — класс с чисто виртуальными методами (copy и invoke было бы достаточно):

        class invoker {
        public:
            invoker() = default;
            virtual ~invoker() = default;
            virtual ReturnType invoke(Args ... args) = 0;
            virtual std::unique_ptr<invoker> clone() = 0;
        };

Тогда можно хранить в union Any указатель на функцию с нужной сигнатурой, и указатель на такой класс. При создании fn::function от функтора (и прочих комбинациях) в union по указателю на класс давайте сторить то, что реализует этот интерфейс + сохранит знание о произвольном функторе — экземпляр такого класса:

        template<class Func>
        class func_invoker : public invoker {
        public:
            explicit func_invoker(Func & func) : func(func) {}

            ReturnType invoke(Args ... args) override {
                return func(std::forward<Args>(args)...);
            }

            std::unique_ptr<invoker> clone() override {
                return std::make_unique<func_invoker<Func>>(func);
            };

            ~func_invoker() override = default;
        private:
            Func func;
        };

В чем преимущества использования такой штуки (по сравнению с текущим решением)?

  1. Безопаснее и оптимальнее за счет использования VDT: нет возможности "забыть сохранить" указатель на нужный метод в коде (хотя можно забыть, например, объявить деструктор виртуальным), вызов по нужному адресу обеспечивает компилятор, пользуется своим хранилищем.
  2. Безопаснее из-за отсутствия reinterpret_cast-ов: компилятор в compile-time выберет правильные приведения типов для аргументов.
Note: See TracTickets for help on using tickets.