Типтерди өчүрүү: std::function, std::any жана өзүңдүн оромоңду түзүү
Конкреттүү типти бирдиктүү, маани семантикасы бар интерфейстин артына жашыруу
std::function берилген кол тамгасы (сигнатурасы) бар каалаган чакырылуучу объектти өчүрөт; std::any каалаган көчүрүлүүчү маанини өчүрөт. Экөө тең жалпы базалык класссыз жана кадимки маани семантикасы менен аткаруу учурундагы полиморфизмди берет - аларды int сыяктуу көчүрөсүз, жылдырасыз жана сактайсыз. Ичинде бул шаблондордун жана виртуалдык диспетчерлештирүүнүн тартиптүү биримдиги, жана бул ыкманы бир жолу көргөндөн кийин өз оромоңду түзө аласың.
- типти "өчүрүү" эмнени билдирерин жана эмне үчүн маани семантикасы маанилүү экенин түшүндүрүү,
- ар түрдүү чакырылуучу объекттерди бир сигнатуранын артына сактоо үчүн
std::functionколдонуу, - белгисиз типтеги маанилерди сактоо жана кайра алуу үчүн
std::anyжанаstd::any_castколдонуу, - өз типти өчүргөн оромоңду түзүү үчүн Concept/Model идиомасын ишке ашыруу,
- баасы жөнүндө ой жүгүртүү: үймөктө бөлүштүрүү, кыйырдык жана кичи буфердик оптимизация.
1. Маселе: базалык класссыз полиморфизм
Сиз көп типтер менен иштеген кодду жазуунун эки жолун билесиз. Шаблондор компиляция учурундагы полиморфизмди берет: template <class T> ар бир тип үчүн жаңы функция чыгарат, аткаруу учурунда чыгымсыз, бирок тип ар бир сигнатурага сиңип кетет - std::vector<T> бир гана T сактай алат. Виртуалдык функциялар аткаруу учурундагы полиморфизмди берет, бирок алар кийлигишкич: ар бир сакталуучу тип сиздин базалык классыңыздан мурасталып, көрсөткүч аркылуу иштелиши керек, ошондуктан сиз маани семантикасын жоготуп, өзүңүзгө көз каранды эмес типтерди (мисалы int же бөтөн структураны) сактай албайсыз.
Типтерди өчүрүү - үчүнчү жол. Ал бир шаблон эмес классты - мисалы Drawable - жазууга мүмкүндүк берет, ал draw() операциясын сунуштаган каалаган типти мурассыз сактай алат жана std::vector<Drawable> ичине көчүрүлө турган кадимки маани катары иштейт. Конкреттүү тип "өчүрүлгөн": курулгандан кийин ором эмнени сактаганын эмес, кантип тартууну гана эстейт.