c++ - الزائد وظيفة امدا




lambda overloading (2)

Lambdas هي في الأساس السكر النحوي لل funators المحددة محليا. بقدر ما أعرف ، لم يكن من المفترض أن يكونوا مثقفين ليتم استدعاؤهم ليتم استدعاؤهم بمعلمات مختلفة. لاحظ أن كل تعبير lambda هو من نوع مختلف ، لذلك حتى الخطأ الفوري جانبا ، لا يمكن أن تعمل التعليمات البرمجية الخاصة بك على النحو المنشود.

ومع ذلك ، يمكنك تحديد operator() مع operator() الزائد operator() . سيكون هذا بالضبط ما ستحصل عليه من lambdas إذا كان ذلك ممكنًا. أنت فقط لا تحصل على بناء جملة مقتضب.

شيء مثل:

void read()
{
    static std::string line;

    struct translator {
          int operator()(int idx) { /* ... */ }
          int operator()(char x)  { /* ... */ }
    };
    translator translate;


    std::getline(std::cin, line);

    int r = translate(static_cast<int>(line[0]));
    int c = translate(static_cast<char>(line[1]));

    std::cout << r << c << std::endl;
}

كيفية تحميل وظيفة lambda محلية بسيطة؟

SSE من المشكلة الأصلية:

#include <iostream>
#include <map>

void read()
{
    static std::string line;
    std::getline(std::cin, line);

    auto translate = [](int idx)
    {
        constexpr static int table[8]{ 7,6,5,4,3,2,1,0 };
        return table[idx];
    };

    auto translate = [](char c)
    {
        std::map<char, int> table{ {'a', 0}, {'b', 1}, {'c', 2}, {'d', 3},
                                             {'e', 4}, {'f', 5}, {'g', 6}, {'h', 7} };
        return table[c];
    };

    int r = translate(static_cast<int>(line[0]));
    int c = translate(static_cast<char>(line[1]));
    std::cout << r << c << std::endl;
}

int main()
{
    read();
    return 0;
}

رسائل الخطأ

error: conflicting declaration 'auto translate'
note: previous declaration as 'read()::<lambda(int)> translate'

من فضلك لا تمانع في عدم التحقق من إدخال المستخدم ، وهذا هو SSE.


لا ، لا يمكنك زيادة الحمل امدا!

lambdas هي الدوافع مجهولة المصدر (أي كائنات وظيفة غير مسمى) ، وليس وظائف بسيطة. لذلك ، الحمولة الزائدة لتلك الكائنات غير ممكن. ما تحاول القيام به أساسا تقريبا

struct <some_name>
{
    int operator()(int idx) const
    {
        return {}; // some int
    }
}translate; // >>> variable name

struct <some_name>
{
    int operator()(char idx) const
    {
        return {}; // some int
    }
}translate; // >>> variable name

وهو أمر غير ممكن ، حيث لا يمكن إعادة استخدام نفس اسم المتغير في C ++.

ومع ذلك ، في c ++ 17 لدينا if constexpr التي يمكن للمرء أن إنشاء فرع الوحيد الذي هو صحيح في وقت الترجمة.

بمعنى الحلول الممكنة هي:

  • قالب واحد varabe امدا. أو
  • lambda عام وابحث عن نوع المعلمة باستخدام if constexpr لفحص if constexpr . (ائتمانات @ NathanOliver )

باستخدام قالب varabe يمكنك القيام بشيء مثل. ( انظر عرض حي على الانترنت )

#include <type_traits> // std::is_same_v

template<typename T>
constexpr auto translate = [](T idx) 
{
    if constexpr (std::is_same_v<T, int>)
    {
        constexpr static int table[8]{ 7,6,5,4,3,2,1,0 };
        return table[idx];
    }
    else if constexpr (std::is_same_v<T, char>)
    {
        std::map<char, int> table{ {'a', 0}, {'b', 1}, {'c', 2}, {'d', 3}, {'e', 4}, {'f', 5}, {'g', 6}, {'h', 7} };
        return table[idx];
    }
};

ويسميها مثل

int r = translate<int>(line[0]);
int c = translate<char>(line[1]);

باستخدام lambda عام (منذ c ++ 14 ) ، سيكون ما يلي: ( انظر عرض حي على الإنترنت )

#include <type_traits> // std::is_same_v

constexpr auto translate = [](auto idx) 
{
    if constexpr (std::is_same_v<decltype(idx), int>)
    {
        constexpr static int table[8]{ 7,6,5,4,3,2,1,0 };
        return table[idx];
    }
    else if constexpr (std::is_same_v<decltype(idx), char>)
    {
        std::map<char, int> table{ {'a', 0}, {'b', 1}, {'c', 2}, {'d', 3}, {'e', 4}, {'f', 5}, {'g', 6}, {'h', 7} };
        return table[idx];
    }
};

واتصل بـ lambda كما تفعل الآن:

int r = translate(static_cast<int>(line[0]));
int c = translate(static_cast<char>(line[1]));




function-object