c++ - एक लैम्ब्डा फ़ंक्शन को अधिभारित करें




lambda overloading (2)

इसलिए नामों को ओवरलोड करने के नियम केवल कुछ प्रकार के फ़ंक्शन नामों (दोनों मुक्त और विधियाँ) के लुकअप पर लागू होते हैं

लैम्ब्डा फ़ंक्शन नहीं हैं, वे एक फ़ंक्शन-कॉल ऑपरेटर के साथ ऑब्जेक्ट हैं। इसलिए दो अलग-अलग मेमनों के बीच ओवरलोडिंग नहीं हो सकती है।

अब, आप फंक्शन ऑब्जेक्ट्स के साथ काम करने के लिए ओवरलोड रिज़ॉल्यूशन प्राप्त कर सकते हैं, लेकिन केवल एक ऑब्जेक्ट के दायरे में। और फिर अगर एक से अधिक operator() , तो ओवरलोड रेज़ोल्यूशन उनके बीच चुन सकता है।

हालांकि, एक लंबोदर के पास एक से अधिक operator() होने का कोई स्पष्ट तरीका नहीं है। हम एक सरल ( c ++ 17 में ) उपयोगिता वर्ग लिख सकते हैं:

template<class...Fs>
struct overloaded : Fs... {
  using Fs::operator()...;
};

और एक कटौती गाइड:

template<class...Fs>
overloaded(Fs...) -> overloaded<Fs...>;

इन दोनों के साथ, हम दो लंबो को ओवरलोड कर सकते हैं:

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

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

auto translate_char = [](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];
};
auto translate = overloaded{ translate_int, translate_char };

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

और हो गया।

overloaded लिखना c ++ 14 और c ++ 11 दोनों में संभव है लेकिन इसके लिए अधिक काम करने की आवश्यकता है और यह कम सुरुचिपूर्ण है। एक बार जब आप समस्या से अवगत हो जाते हैं, तो एक समाधान खोजना जो मेल खाता है कि C ++ सुविधाओं के तरीके में आपका विशेष संकलक क्या समर्थन करता है, कठिन नहीं होना चाहिए।

एक साधारण स्थानीय लैम्ब्डा फ़ंक्शन को कैसे अधिभारित करें?

मूल समस्या का 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 है।


नहीं, आप लंबोदर को अधिभार नहीं दे सकते!

लैम्ब्डा अनाम फ़ंक्शनलर्स (यानी अनाम फ़ंक्शन ऑब्जेक्ट्स) हैं, और सरल फ़ंक्शन नहीं हैं। इसलिए, उन वस्तुओं को ओवरलोड करना संभव नहीं है। आप मूल रूप से जो करने की कोशिश कर रहे हैं वह लगभग है

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 है if constexpr केवल उसी ब्रांच को if constexpr कर सकता है जो कि संकलन के समय सही है।

मतलब संभव समाधान हैं:

  • एक एकल varabe टेम्पलेट लैम्ब्डा। या
  • एक सामान्य लैम्ब्डा और if constexpr चेक के लिए decltype का उपयोग करके पैरामीटर के प्रकार का पता if constexpr । (क्रेडिट @Nathanliliver )

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]);

सामान्य लैम्ब्डा ( 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];
    }
};

और लैम्बडा को कॉल करें जैसा कि आप अभी करते हैं:

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




function-object