استفاده از %at% به جای * - هفت خط کد انجمن پرسش و پاسخ برنامه نویسی

استفاده از %at% به جای *

+1 امتیاز

من توی یکی از سوالات stack این کد رو دیدم که به جای استفاده از a->at(1  از این کد استفاده شده بود

چجوری کار می کنه این  ؟

template<typename LHS> struct at_lhs_t { LHS lhs; };
static struct at_t {} at;
template<typename LHS>
at_lhs_t<LHS> operator%( LHS&& lhs, at_t )
{ return {std::forward<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)) ); }

class MyClass
{
public:
    void operator[](int n)
    {
        std::cout<<"In []";
    }
};
int main()
{
    MyClass *a=new MyClass;
    a %at% 1;
}

 

سوال شده فروردین 1, 1393  بوسیله ی Mad (امتیاز 245)   10 35 47
دوباره تگ گذاری شد مرداد 28, 1393 بوسیله ی BlueBlade

1 پاسخ

+2 امتیاز
 
بهترین پاسخ
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[] استفاده می کنیم .

پاسخ داده شده فروردین 1, 1393 بوسیله ی BlueBlade (امتیاز 15,315)   15 18 89
انتخاب شد فروردین 2, 1393 بوسیله ی Mad
...