Войти
ПрограммированиеФорумОбщее

C++ отложенное изменение свойств объекта в цепочке вызовов, независимо от порядка вызовов методов в цепочке (2 стр)

Страницы: 1 2 3 Следующая »
#15
(Правка: 12:43) 12:39, 8 апр. 2019

1 frag / 2 deaths
> Но вообще я не могу понять, на кой это надо.
Практический пример: рендер текста с разным выравниванием и свойствами без указания их через параметры.
Хочу чтобы можно было так:
Font->printf("health: %d", health);
И вот так:
Font->printf("health: %d", health).AlignRight();
Основная идея - главное действие идет в цепочке первым, а следом навешиваются разные модификаторы по желанию.

#16
12:44, 8 апр. 2019

Vitorio
> главное действие идет в цепочке первым, а следом навешиваются разные
> модификаторы по желанию.
А почему ты предлагаешь нелогичые конструкции? Я читаю как "сначала выводим, потом двигаем влево". А потом висну "как можно двигать, если уже вывели".
Ну или хотя бы

Font->Message("health: %d", health).AlignLeft().Print()?
#17
(Правка: 12:53) 12:53, 8 апр. 2019

Vitorio
> Font->printf("health: %d", health).AlignLeft();
> Основная идея - главное действие идет в цепочке первым, а следом навешиваются
> разные модификаторы по желанию.

паттерн называется "атомарный стрим".

суть идеи:
первый вызов цепочки порождает временный объект-аккумулятор.
который накапливает все "изменения".

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

пример:
https://rextester.com/DNDVO55765

#include <iostream>
#include <sstream>


struct Font;

struct Accumulator
{
    Accumulator(const Accumulator&) = delete;
    Accumulator(Accumulator&&)      = delete;
    
    Accumulator& operator=(const Accumulator&) = delete;
    Accumulator& operator=(Accumulator&&)      = delete;
    
    
    Accumulator(Font& owner, const char* text)
        : ss()
        , aglin_left(false)
        , owner(&owner)
    { ss << text; }
    
    Accumulator& AlignLeft()
    {
        aglin_left = true;
        return *this;
    }
    
    ~Accumulator();
    
    std::stringstream ss;
    
    bool aglin_left = false;
    Font* owner;

};


struct Font
{
    Accumulator printf(const char* text)
    {
        return { *this, text };
    }

    void commit(const Accumulator& acc)
    {
        if(acc.aglin_left)
            std::cout << "[AlignLeft] ";
        std::cout << acc.ss.str() << '\n';
    }
};


Accumulator::~Accumulator()
{
    this->owner->commit(*this);
}


int main()
{
    Font font;
    
    font.printf("ololo").AlignLeft();
}
#18
(Правка: 12:56) 12:56, 8 апр. 2019

1 frag / 2 deaths
> Я читаю как "сначала выводим, потом двигаем влево". А потом висну "как можно
> двигать, если уже вывели".
Ты так читаешь потому, что тебя так научили читать. Мой вариант идет вразрез с известными тебе правилами, но и его тоже можно принять за правило:) И Ц++ может и такой изврат, что доказывает вариант от Faceroll :)
Вариант с финализирующим print получается длиннее на 1 метод...

Upd:
Kartonagnick, спасибо! Буду курить код!

#19
12:57, 8 апр. 2019

Vitorio
> Ты так читаешь потому, что тебя так научили читать.
?овелан аварпс ьшеатич ыт ,ондал аД

#20
13:00, 8 апр. 2019

Vitorio
> Font->printf("health: %d", health).AlignRight();

Не надо выдумывать никакую обратную логику.
С++ умеет в процедурку и в ООП, значит этим и надо пользоваться.
То, что вы хотите, делается примерно так:

class Font {
public:
    Text printf(char* txt, args ...);
};

class Text {
public:
    Text& AlignRight() {
        //some magic;
        return *this;
    }
    ~Text() { std::cout << _message; };

private:
    char* _message;
};

Хотя, лучше, конечно, печатать не в деструкторе, а отдельным методом, как уже было предложено выше - так код будет гораздо понятнее для других людей.

#21
13:03, 8 апр. 2019

Помнится, _Winnie так предлагал спрайты рисовать:
https://users.livejournal.com/-winnie/229311.html

#22
13:05, 8 апр. 2019

Vitorio
Ты наркоман, прочь от клавиатуры, иди мети дворы.

#23
13:06, 8 апр. 2019

Рабочая логика в деструкторе плохо пахнет.

#24
13:09, 8 апр. 2019

1 frag / 2 deaths
> Рабочая логика в деструкторе плохо пахнет.

Всмысле? У того же smart_ptr основная работа - это подчищать за другими мусор и она в деструкторе делается.

#25
13:12, 8 апр. 2019

1 frag / 2 deaths
> Рабочая логика в деструкторе плохо пахнет.

вы это так пишите, будто бы рабочая логика в деструкторе
чем то принципиально отличается от рабочей логики ещё где нибудь.

#26
13:13, 8 апр. 2019

=A=L=X=
Как же вы бесите, все мои старания в прах уничтожили, я и так и сяк старался найти формулировку, что-то типа "задач, не относящихся к освобождению ресурсов" или хрен знает ещё как это назвать, нет же, всё равно вы докопаетесь чисто в лоб.

#27
13:14, 8 апр. 2019

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

#28
13:18, 8 апр. 2019

=A=L=X=
Да ты вообще не напрягся блин. Нет чтоб на секунду хоть подумать "ну по любому же он знает про смартпоинтеры, что же он имел в виду", нет, ты сходу ляпаешь.

#29
13:19, 8 апр. 2019

В деструкторах есть проблемы с исключениями, но так как геймдевелоперы не используют исключения то все ок :trollface

Страницы: 1 2 3 Следующая »
ПрограммированиеФорумОбщее