Внешний конструктор
От: kaa.python Ниоткуда РСДН профессионально мёртв и завален ватой.
Дата: 19.08.15 07:36
Оценка: 46 (3)
Довольно элегантное решение для читабельной, одношаговой инициализации сложных структур данных в C++: http://gerardmeier.com/foreign-constructors-cpp
В кратце:
struct Font {
    ...
    // The foreign constructor.
    Font(std::function visit) {
        visit(*this);
    }
};
class Button {
    const Font font = Font([] (Font& font) {
        font.weight = Weight::VeryBold;
        font.slant  = Slang::Oblique;
        font.halign = Anchor::Left;
    });
};

Единственное что мне не нравится, доступа к protected/private полям класса без сеттеров уже не получить, что делает подобный подход чуть менее читабельным.
Re: Внешний конструктор
От: Jack128  
Дата: 19.08.15 07:57
Оценка: 68 (1) +1
Здравствуйте, kaa.python, Вы писали:

KP>Довольно элегантное решение для читабельной, одношаговой инициализации сложных структур данных в C++: http://gerardmeier.com/foreign-constructors-cpp

KP>В кратце:
KP>
struct Font {
KP>    ...
KP>    // The foreign constructor.
KP>    Font(std::function visit) {
KP>        visit(*this);
KP>    }
KP>};
KP>class Button {
KP>    const Font font = Font([] (Font& font) {
KP>        font.weight = Weight::VeryBold;
KP>        font.slant  = Slang::Oblique;
KP>        font.halign = Anchor::Left;
KP>    });
KP>};
KP>

KP>Единственное что мне не нравится, доступа к protected/private полям класса без сеттеров уже не получить, что делает подобный подход чуть менее читабельным.

а чем это лучше обычного
const Font font = [] () { 
    auto font = Font();
    font.weight = Weight::VeryBold;
    font.slant  = Slang::Oblique;
    font.halign = Anchor::Left;
    return font;
}();
Re[2]: Внешний конструктор
От: Кодт Россия  
Дата: 19.08.15 09:19
Оценка:
Здравствуйте, Jack128, Вы писали:

J>а чем это лучше обычного


Тем, что не требует Copy Constructible.
Перекуём баги на фичи!
Re: Внешний конструктор
От: Кодт Россия  
Дата: 19.08.15 09:21
Оценка:
Здравствуйте, kaa.python, Вы писали:

KP>Довольно элегантное решение для читабельной, одношаговой инициализации сложных структур данных в C++: http://gerardmeier.com/foreign-constructors-cpp


Сама идея передачи функции в конструктор интересна. Может быть, где-то ещё пригодится.
Но вот конкретно здесь — есть проблемы.
— тяжеловесная std::function вместо шаблона
— как уже заметил Jack128, вызов может выродиться (у него, правда, ценой копирования, в надежде на NRVO)

Надо подумать, может, и двухфазную инициализацию можно в похожий паттерн всунуть.
Перекуём баги на фичи!
Re[2]: Внешний конструктор
От: kaa.python Ниоткуда РСДН профессионально мёртв и завален ватой.
Дата: 19.08.15 09:23
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Надо подумать, может, и двухфазную инициализацию можно в похожий паттерн всунуть.


Вот что бы мне хотелось здесь, так это получит доступ к приватным полям инициализируемого класса. Но, похоже что, без вариантов тут
Re[3]: Внешний конструктор
От: Кодт Россия  
Дата: 19.08.15 09:31
Оценка:
Здравствуйте, kaa.python, Вы писали:

KP>Вот что бы мне хотелось здесь, так это получит доступ к приватным полям инициализируемого класса. Но, похоже что, без вариантов тут


Ну так если есть приватные поля, то и способы работы с ними приватные.
Выходов три
class Secret {
private:
  int foo_, bar_, buz_, xyz_;
  void setup_xyz();
public:
  template<class F, class B, class A>
  Secret(F do_foo, B do_bar, A do_all) // настроечных функций может быть больше одной ;)
  {
    foo_ = do_foo(*this); // (1a)
    do_bar(bar_);         // (1b)
    do_all(*this);
  }
  void setup_buz();       // (2)
  friend class Xyzzer;    // (3)
};
Перекуём баги на фичи!
Re[3]: Внешний конструктор
От: uzhas Ниоткуда  
Дата: 19.08.15 09:41
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Тем, что не требует Copy Constructible.


конкретно в указанном коде copy constructible требуется.
смотрим:
http://ideone.com/ssjk0k
http://stackoverflow.com/questions/1051379/is-there-a-difference-in-c-between-copy-initialization-and-direct-initializati

требование можно избежать, если написать так:
Font f([](Font& x) { ... });
Re: Внешний конструктор
От: landerhigh Пират  
Дата: 19.08.15 09:59
Оценка:
Здравствуйте, kaa.python, Вы писали:

KP>Единственное что мне не нравится, доступа к protected/private полям класса без сеттеров уже не получить, что делает подобный подход чуть менее читабельным.


А еще оно работает только в случае, если мемберы имеют конструкторы по умолчанию.
Ну и кода сильно меньше не получится в любом случае.
www.blinnov.com
Re[3]: Внешний конструктор
От: Jack128  
Дата: 19.08.15 10:36
Оценка:
Здравствуйте, Кодт, Вы писали:

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


J>>а чем это лучше обычного


К>Тем, что не требует Copy Constructible.


Дык вроде копи — не нужен. Только мув. http://ideone.com/Eoeilq
Re: Внешний конструктор
От: PM  
Дата: 19.08.15 10:45
Оценка:
Здравствуйте, kaa.python, Вы писали:

Точно такие же комментарии были в теме на reddit

Мне больше всего понравился вариант с лямбдой :

const auto font = [](){
    Font font;
    font.weight = Weight::VeryBold;
    font.slant  = Slang::Oblique;
    font.halign = Anchor::Left;
    return font;
};
Re[2]: Внешний конструктор
От: uzhas Ниоткуда  
Дата: 19.08.15 11:06
Оценка:
Здравствуйте, PM, Вы писали:

PM>Мне больше всего понравился вариант с лямбдой :


какие жертвы ради одного const
оно того не стоит
Re[3]: Внешний конструктор
От: PM  
Дата: 19.08.15 11:51
Оценка:
Здравствуйте, uzhas, Вы писали:

PM>>Мне больше всего понравился вариант с лямбдой :


U>какие жертвы ради одного const

U>оно того не стоит

Как обычно, зависит от задачи. Может потребоваться инициализировать статическую константу или передать временный объект в функцию. В C++03 приходилось создавать рядом вспомогательную функцию, сейчас для этого есть лямбда по месту использования. Синтаксический оверхед, но удобный.
Re: Внешний конструктор
От: Шахтер Интернет  
Дата: 19.08.15 13:39
Оценка: 1 (1) +1
Здравствуйте, kaa.python, Вы писали:

KP>Довольно элегантное решение для читабельной, одношаговой инициализации сложных структур данных в C++: http://gerardmeier.com/foreign-constructors-cpp

KP>В кратце:
KP>
struct Font {
KP>    ...
KP>    // The foreign constructor.
KP>    Font(std::function visit) {
KP>        visit(*this);
KP>    }
KP>};
KP>class Button {
KP>    const Font font = Font([] (Font& font) {
KP>        font.weight = Weight::VeryBold;
KP>        font.slant  = Slang::Oblique;
KP>        font.halign = Anchor::Left;
KP>    });
KP>};
KP>

KP>Единственное что мне не нравится, доступа к protected/private полям класса без сеттеров уже не получить, что делает подобный подход чуть менее читабельным.

Сделай производный класс. Кстати, в его конструкторе можно обращаться к полям и методам короче и есть доступ к protected.

class Button
 {
   class CustomFont : public Font
    {
     public:

      CustomFont()
       {
        weight = Weight::VeryBold ;
        slant  = Slang::Oblique ;
        halign = Anchor::Left ;
       }
    };

   const CustomFont font;
 };
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: Внешний конструктор
От: -MyXa- Россия  
Дата: 19.08.15 14:47
Оценка:
Здравствуйте, kaa.python, Вы писали:

KP>class Button {

KP> const Font font = Font([] (Font& font) {
KP> font.weight = Weight::VeryBold;
KP> font.slant = Slang::Oblique;
KP> font.halign = Anchor::Left;
KP> });
KP>};

Многовато букв же — 8 раз слово (F)font.

С помощью Boost.Parameter я делаю короче:
auto const small_font = make(_size = 20.f, _locale = L"ru-RU"); // перед этим, правда, ещё трёхэтажный using namespace


А, вообще, если подумать — чего мы добиваемся? Чтобы по всему коду были разбросаны захадкоженные параметры (шрифтов)? Это не хорошо.
Если не поможет, будем действовать током... 600 Вольт (C)
Re: Внешний конструктор
От: jazzer Россия Skype: enerjazzer
Дата: 20.08.15 03:19
Оценка:
Здравствуйте, kaa.python, Вы писали:

Ну этому способу сто лет в обед, но главное — это не конструктор же, это двухфазка
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]: Внешний конструктор
От: kaa.python Ниоткуда РСДН профессионально мёртв и завален ватой.
Дата: 20.08.15 03:41
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Ну этому способу сто лет в обед, но главное — это не конструктор же, это двухфазка


В каком месте это двухфазка?
Re[3]: Внешний конструктор
От: jazzer Россия Skype: enerjazzer
Дата: 20.08.15 03:52
Оценка: 2 (1)
Здравствуйте, kaa.python, Вы писали:

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


J>>Ну этому способу сто лет в обед, но главное — это не конструктор же, это двухфазка


KP>В каком месте это двухфазка?


У тебя все члены инициализируются (по умолчанию), а потом начинаются присваивания поверх уже инициализированных членов. Инициализировать члены таким способом не удастся, плюс накладывается дополнительное ограничение насчет поддержки конструирования по умолчанию и последующего изменения (присваиванием или еще как) — то есть константные члены тоже идут лесом.

В общем, стандартные прелести двухфазки
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Отредактировано 20.08.2015 4:01 jazzer . Предыдущая версия .
Re: Внешний конструктор
От: Aртёмка Австралия жж
Дата: 20.08.15 04:26
Оценка:
Здравствуйте, kaa.python, Вы писали:

KP>Довольно элегантное решение для читабельной, одношаговой инициализации

Чем паттерн Builder не угодил?
const Font f = FontBuilder().bold(true).strike(false).color(Color.red).build();

Оно, конечно, многошаговое- но так оптимизирующий компилятор разве не вычистит лишние операции?
Re[4]: Внешний конструктор
От: uzhas Ниоткуда  
Дата: 20.08.15 07:18
Оценка:
Здравствуйте, jazzer, Вы писали:

J>В общем, стандартные прелести двухфазки


на самом деле это отличается от двухфазовой инициализации, т.к. к моменту завершения работы конструктора объект полностью инициализирован и находится в консистентном состоянии. готов к использованию.
вдобавок, при таком подходе все равно не получится сделать shared_from_this при инициализации (или что-то уже придумали?), стандартная двухфазка нужна в этом случае
Re[2]: Внешний конструктор
От: enji  
Дата: 20.08.15 11:32
Оценка:
Здравствуйте, Aртёмка, Вы писали:

Aё>const Font f = FontBuilder().bold(true).strike(false).color(Color.red).build();


Aё>Оно, конечно, многошаговое- но так оптимизирующий компилятор разве не вычистит лишние операции?


Это ж кучу вспомогательного кода надо написать.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.