170 похожих чатов

Посмотрите, вот при таком подходе есть ли подводные камни?


#include <any>
#include <functional>
#include <iostream>

struct ICar
{

virtual std::string alarm() const = 0;

virtual ~ICar() = default;
};

struct Ferrari : ICar
{

std::string alarm() const override
{
return std::string{"Ferrari"};
}
};

struct Lada : ICar
{

std::string alarm() const override
{
return std::string{"Lada"};
}
};

struct Nocar : ICar
{

std::string alarm() const override
{
return std::string{"NO CAR"};
}
};

// кладет в себя производный тип как есть, но при этом еще и сразу кладет
// в указатель на функцию как скастовать его обратно в нужный тип
// когда надо обратно он прогоняет сквозь функцию кастования и получает изначальный тип
// но возвращаем в указатель на базовый наружу.
// этот подход убирает телодвижения с виртуальными clone() если б мы просто хранили указатель на базовый
class Carpoly
{
public:
template <typename ConcreteCar>
Carpoly(ConcreteCar &&concrete_type)
: storage{std::forward<ConcreteCar>(concrete_type)},
getter{[](std::any &storage) -> ICar & { return std::any_cast<ConcreteCar &>(storage); }}
{
}

ICar *operator->()
{
return &getter(storage);
}

private:
std::any storage;
ICar &(*getter)(std::any &);
};

struct Garage
{

template <class T> auto make_car()
{
return Carpoly{T{}};
}

void set_lada()
{
mycar_ = make_car<Lada>();
}

void set_ferrari()
{
mycar_ = make_car<Ferrari>();
}

std::string beep()
{
return mycar_->alarm();
}

Carpoly mycar_{Nocar{}};
};

int main()
{
Garage mygarage;
mygarage.set_lada();
std::cout << mygarage.beep() << std::endl;
mygarage.set_ferrari();
std::cout << mygarage.beep() << std::endl;

return 0;
}

2 ответов

6 просмотров

А чем не устроил вариант сразу же с хранением указателя на ICar?

А зачем тут виртуальный clone? Нам же просто надо вызвать метод alarm у машины. Это же обычный виртуальный вызов. Зачем городить городушки в виде Carpoly, если там в итоге все равно вернется указатель на ICar? void beep(ICar & car) { car.alarm(); } Lada lada; beep(lada); Ferrari ferrari; beep(ferrari);

Похожие вопросы

Обсуждают сегодня

а зачем этот вопрос для удаления из чата?
Mёdkinson Medvezhkin
63
TCodePointer = record cp: CodePointer; name: string; cnt: Integer; next: TCodePointerArray; // этот тип ещё неизвестен end; TCodePointerArray = array of ...
notme
9
Привет ) есть такой кусок кода, он считывает ini файл. my $conf = Config::IniFiles->new( -file => $ini_file ); if (!$conf) { $self->my_die('cannot_read_cfg', ...
Kolya lastname
7
Добрый день. Хочу сделать отрисовку по команде на панели. Почему-то рисуется только при втором вызове. С чем может быть связано, не подскажете? procedure TForm1.FormDblClick(...
Kirill Filippenok
20
Всем привет! Подскажите. Я написал приложение на Delphi 10.2 Tokyo под Windows 10. И передо мной стал вопрос о том чтобы сделать это приложение кроссплатформенным (под Linux и...
Дмитрий Завгородний
24
Блин, интересно, кто-нибудь когда-нибудь переписывал какую-нибудь игру с x86 на arm? Вообще, такое возможно?
Alan 🔝 Бэброу
13
Эх кто-то пришел и весь праздник испортил :( You need complex FBX scene importing setup to change things on import? good luck with that. You need navigation and pathfinding? g...
Serg Gini
5
Всем привет! Нужен совет от опытных. Переношу свой проект с Делфи 10.2 Токио на Лазарус 3.2 установленный через инсталлятор fpcupdeluxe-x86_64-win64. При импортировании проект...
Дмитрий Завгородний
7
здравствуйте, братья, кто-нибудь знает, как работать с Swift.com или Swift.net?
Ozzy
6
Всем доброго дня! Подскажите может кто использовал связку Pagebuilder + Clientsetting. Сами параметры с типом pagebuilder в модуле Clientsetting работают нормально, можно такж...
Александр Добриков
12
Карта сайта