پردهٔ پشتی std::any: مفهوم Type Erasure به زبان ساده
خلاصهٔ کاملتر
نویسنده تو این آموزش توضیح میده پشت std::any در ++C چه خبره و یه تکنیک کلاسیک به اسم type erasure (پاکسازی نوع) رو از صفر میسازه. ایدهٔ کلی اینه که نوعهای مشخص (concrete) پشت یه پوشش کوچیک و یکدست پنهان بشن.
اول از چندریختی (polymorphism) معمولی با اینترفیس شروع میکنه: یه کلاس پایه با متد مجازی (مثلاً Shape با area()) تعریف میشه و کلاسهایی مثل Square و Circle ازش ارثبری میکنن. ولی این روش یه شرط داره: نوعها باید بتونن از یه پایهٔ مشترک ارث ببرن.
نویسنده میگه گاهی این ممکن نیست — مثلاً نوعهایی مثل int یا std::string که نمیتونی تغییرشون بدی. روش جایگزین استفاده از templateـه، ولی اون هم دو ایراد داره: یه نوع پایهٔ مشترک در زمان اجرا بهت نمیده (پس نمیتونی Square و Circle رو تو یه آرایه نگه داری)، و templateها بهسرعت تو کل کدبیس پخش میشن.
راهحل type erasure ترکیب این دوتاست: یه اینترفیس داخلی تعریف میکنی و یه کلاس wrapperِ templated میسازی که از اون ارث میبره و فراخوانیها رو به شیء داخلی فوروارد میکنه. به این ترتیب کامپایلر برای هر نوع، نسخهٔ لازم رو خودش تولید میکنه:
template <typename T>
class ShapeWrapper : public Shape {
T shape_;
public:
explicit ShapeWrapper(T shape) noexcept : shape_{std::move(shape)} {}
auto area() const noexcept -> double override { return shape_.area(); }
};نویسنده میگه دو اسم استانداردِ پذیرفتهشده برای این الگو وجود داره: اینترفیسی که برخلافش برنامه مینویسی «Concept» نامیده میشه و wrapperِ templated «Model». با پنهانکردن کل این ماشینآلات پشت یه کلاس بیرونی، استفادهکننده دیگه با اینترفیسها و templateهای داخلی سروکار نداره و دقیقاً مثل std::any کار میکنه.
نکات کلیدی:
- type erasure نوعهای مشخص رو پشت یه پوشش یکدست پنهان میکنه
- وقتی نوعها نمیتونن از یه پایهٔ مشترک ارث ببرن به کار میاد
- یه wrapperِ templated فراخوانیها رو به شیء داخلی فوروارد میکنه
- اینترفیس داخلی «Concept» و wrapper «Model» نامیده میشه




