Кемчиликсиз узатуу (perfect forwarding)
Аргументти маанисинин категориясын жоготпой ороочу аркылуу узатуу
const беле же жок беле - баары сакталат. Аны иштетүүчү үч бөлүк: узатуу шилтемеси (чыгарылуучу типтеги T&&), компилятор колдонгон шилтемелерди жыйноо эрежелери жана std::forward - чакыруу учурунда баштапкы маанинин категориясын калыбына келтирүүчү шарттуу кастинг.
- экөө тең
T&&деп жазылса да, rvalue-шилтеме менен узатуу шилтемесинин айырмасын түшүндүрүү, - шилтемелерди жыйноонун төрт эрежесин кол менен колдонуу,
std::forward<T>туура колдонуу (жана бул жердеstd::moveэмне үчүн ката экенин айтуу),- ач конструктор тузагынан качкан вариативдик фабрика функцияларын жана узатуучу конструкторлорду жазуу.
1. Маселе: маанинин категориясын сактаган ороочу
Маанинин категорияларын жылдыруу семантикасы курсунан билесиз: lvalue туруктуу объектти атайт (анын дарегин алса болот), а rvalue - жылдырса боло турган убактылуу объект. Жылдыруу семантикасы убактылуу объект чын эле rvalue катары таанылып, анын ресурстары көчүрүлбөй уурдалганда гана пайда берет.
Ичке ороочуну элестетиңиз - логирлөө катмары, фабрика, контейнердин emplace - ал аргументти кабыл алып, дароо максаттуу sink функциясына берет. Биз ороочу көрүнбөс болушун каалайбыз: чакыруучу убактылуу объект берсе, sink убактылууну көрүшү керек (жана жылдырсын); аталган объект берсе, sink lvalue көрүшү керек (жана көчүрсүн). Жөнөкөй аракеттердин баары ийгиликсиз:
void wrap(T v)- маани боюнча кабыл алат, ар бир аргументтин ашыкча көчүрмөсүн же жылдырмасын талап кылат.void wrap(const T& v)- дайыма const-ка lvalue-шилтеме;sinkчыныгы убактылуудан да эч качан жылдыра албайт.void wrap(T& v)- rvalue жана const-объекттерди толугу менен четке кагат.
const/const эмес жана lvalue/rvalue ар бир айкалышы үчүн өзүнчө перегрузка жазуу масштабдалбайт: n параметрлүү функцияга 2^n перегрузка керек болмок. Кемчиликсиз узатуу бүт маселени бир шаблон менен чечет.