غير قادر على إنشاء قوالب الوظائف التي تستخدم Decltype لاستنتاج نوع الإرجاع ، إذا تم استدعاؤها من داخل Lambda؟

StackOverflow https://stackoverflow.com/questions/2335530

سؤال

أحاول استخدام C ++ 0x ، وخاصة تعبير Lambda وإلغاء تبسيط بعض التعليمات البرمجية الخاصة بي ، باستخدام برنامج التحويل البرمجي MSVC10 RC.

لقد واجهت مشكلة غريبة للغاية:

template <typename F>
auto foo(F f) -> decltype(f()){
  return f();
}

template <typename F>
void bar(F f){
  f();
}

int main() {
  bar([](){
    foo([]() { }); // error C2893: Failed to specialize function template ''unknown-type' foo(F)'
  });
}

كما هو موضح في التعليق ، يقوم المترجم بإنشاء خطأ على السطر foo([]() { }).

أكره أن أصرخ "Bug Pres" ، لكنني حقًا لا أستطيع رؤية أي تفسير جيد لهذا الخطأ. على ما يبدو ، بينما داخل تعبير Lambda الخارجي ، لا يمكن للمترجم تخصص foo قالب وظيفة لامبادا الداخلية.

ومع ذلك ، إذا كان تعريف foo تم تغييره إلى Hardcode نوع الإرجاع ، مثل هذا:

template <typename F>
void foo(F f){
  return f();
}

ثم كل شيء يجمع على ما يرام.

هل هناك بعض الغموض الغامضة للإعلان عند استخدامها لاستنتاج نوع إرجاع معلمات تعبير Lambda داخل نطاق Lambda آخر لست على علم به؟

هل كانت مفيدة؟

المحلول

هذه مجرد بعض حالات الاختبار للناس لمراقبة.

يعمل

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

void dummy() {}

int main()
{
    auto x = []()
            {   // non-lambda parameter
                foo(dummy);
            };
}

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto f = [](){};
    auto x = [&]()
            {    // pre-defined lambda
                foo(f);
            };
}

فشل

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto x = []()
            {   // in-argument lambda
                foo([]{});
            };
}

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto x = []()
            {   // in-scope lambda
                auto f = []{};
                foo(f);
            };
}

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto x = []()
            {   // in-scope lambda, explicit return
                // (explicit return type fails too, `-> void`)
                auto f = [](){ return; };
                foo(f);
            };
}

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto x = []()
            {   // in-argument lambda, explicit return non-void
                // (explicit return type fails too, `-> int`)
                foo([]{ return 5; }); 
            };
}

لذلك يبدو أن الأمر يتعلق بالنطاق و ال void نوع lambda الداخلية ، حتى عندما يكون صريحا.(?)

نصائح أخرى

طبيعة "Auto" هي السماح للمترجم بحساب النوع. ولكن مثالك الأول يحتوي على مراجع متكررة على بعضها البعض ، لذا لحساب Auto's لـ Foo ، تحتاج إلى شريط وإنشاء مثيل للشريط الذي تحتاجه إلى FOO.

من ناحية أخرى ، يقول المثال الثاني بشكل صريح عن المترجم: "يجب أن يكون مؤشرًا للعمل ، لذا تهدأ لبعض الوقت". نظرًا لأن المؤشر إلى الوظيفة محسوبة جيدًا ، يعرف برنامج التحويل البرمجي نوعًا ما هو محجوز بالضبط. فقط للتناظرية: قارن إعلان الأعضاء إلى الأمام

struct A; //forward
...
A a1; //this is an error
A *a2; //this is correct since pointer calculated in bytes
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top