template<typename LHS>
struct at_lhs_t
{
LHS lhs;
};
کد بالا نیازی به توضیح نداره یک struct سادست
static struct at_t
{
} at;
این هم یک struct دیگست کلمه static کارش اینه که به کامپایلر می گه از این struct فقط توی همین فایل استفاده کن این لینک رو ببین : namespace بدون نام
می تونستین static رو هم نزارین .
template<typename LHS>
at_lhs_t<LHS> operator%( LHS&& lhs, at_t )
{
return {std::forward<LHS>(lhs)};
}
کد بالا هم operator% که global هست رو overload کردیم
و یک نکته هم هست این که کد بالا از universal refrence و std::forward استفاده کرده
در مورد universal refrence , std::forward توی این ۲ تا لینک توضیح دادم قبلا : منظور از move در c++11 و std::forward یعنی چی ؟
مقدار بازگشتی این تابع یک struct از نوع at_lhs_t هستش که قیلد lhs اش همون lhs ای هست که به تابع فرستادیم
template<typename LHS, typename RHS>
auto operator%( at_lhs_t<LHS>&& lhs, RHS&& rhs )->decltype( (std::forward<LHS>(lhs.lhs))->operator[](std::forward<RHS>(rhs)) )
{
return ( (std::forward<LHS>(lhs.lhs))->operator[](std::forward<RHS>(rhs)) );
}
توی کد بالا مقدار بازگشتی از تابع auto هستش زمانی که از auto استفاده میشه برای بازگشت باید مقدار return شده هم مشخص باشه بوسیله <- (البته قراره از c++14 به بعد این محدودیت برداشته بشه )
کد زیر
( (std::forward<LHS>(lhs.lhs))
همون طوری که بالا هم گفتم دقیقا همون مقداری که قبل از ارسال به تابع داشتیم رو به ما بر می گردونه
نهایتا هم که operator -> استفاده شده
( (std::forward<LHS>(lhs.lhs))->operator[](std::forward<RHS>(rhs)) );
برای مشخص کردن مقدار بازگشتی هم کافیه که decltype استفاده کنیم روی همین عبارت :
->decltype( (std::forward<LHS>(lhs.lhs))->operator[](std::forward<RHS>(rhs)) )
داخل main ما این کد رو داریم :
a %at% 1;
کد بالا به این شکل اجرا میشه
(a %at)%1
یعنی اول یکبار operator ٪ اول صدا زده میشه و یک struct از نوع at-lhs_t برگشت داده میشه
بعد operator% دوم صدا زده میشه و نهایتا داخل operator از operator[] استفاده می کنیم .