c++ - Überladen Sie eine Lambda-Funktion




overloading c++17 (2)

Daher gelten die Regeln zum Überladen von Namen nur für bestimmte Arten der Suche nach Funktionsnamen (sowohl freie als auch Methoden).

Lambdas sind keine Funktionen, sie sind Objekte mit einem Funktionsaufrufoperator. Es kann also nicht zu einer Überlastung zwischen zwei verschiedenen Lambdas kommen.

Jetzt können Sie eine Überladungsauflösung erhalten, um mit Funktionsobjekten zu arbeiten, jedoch nur innerhalb des Bereichs eines einzelnen Objekts. Und wenn es dann mehr als einen operator() , kann eine Überlastungsauflösung zwischen ihnen wählen.

Ein Lambda hat jedoch keinen offensichtlichen Weg, mehr als einen operator() . Wir können eine einfache (in C ++ 17 ) Utility-Klasse schreiben, um uns zu helfen:

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

und ein Abzugsleitfaden:

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

Mit diesen beiden können wir zwei Lambdas überladen:

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

und fertig.

overloaded Schreiben ist sowohl in c ++ 14 als auch in c ++ 11 möglich , erfordert jedoch mehr Arbeit und ist weniger elegant. Wenn Sie sich des Problems bewusst sind, sollte es nicht schwierig sein, eine Lösung zu finden, die den von Ihrem Compiler unterstützten C ++ - Funktionen entspricht.

Wie überlastet man eine einfache lokale Lambda-Funktion?

SSE des ursprünglichen Problems:

#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;
}

Die Fehlermeldungen

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

Bitte prüfen Sie die Benutzereingaben nicht. Dies ist eine SSE.


Lambdas sind im Grunde syntaktischer Zucker für lokal definierte Funktoren. Soweit ich weiß, sollten sie niemals überladen werden, um mit anderen Parametern aufgerufen zu werden. Beachten Sie, dass jeder Lambda-Ausdruck von einem anderen Typ ist. Abgesehen von dem unmittelbaren Fehler kann Ihr Code nicht wie beabsichtigt funktionieren.

Sie können jedoch einen Funktor mit einem überladenen operator() . Dies wird genau das sein, was Sie von Lambdas bekommen würden, wenn es möglich wäre. Sie erhalten nur nicht die knappe Syntax.

So etwas wie:

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;
}






function-object