c++ - Sobrecarregar uma função lambda




overloading c++17 (2)

Lambdas são basicamente açúcar sintático para functores definidos localmente. Tanto quanto eu sei, eles nunca foram feitos para serem sobrecarregados para serem chamados com parâmetros diferentes. Observe que toda expressão lambda é de um tipo diferente; portanto, mesmo com o erro imediato, seu código não pode funcionar como pretendido.

No entanto, você pode definir um functor com um operator() sobrecarregado operator() . Será exatamente o que você obteria das lambdas, se possível. Você simplesmente não obtém a sintaxe concisa.

Algo como:

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

Como sobrecarregar uma função lambda local simples?

SSE do problema original:

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

As mensagens de erro

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

Por favor, não se importe de não verificar a entrada do usuário, este é um SSE.


Não, você não pode sobrecarregar o lambda!

Os lambdas são functores anônimos (ou seja, objetos de função sem nome), e não funções simples. Portanto, sobrecarregar esses objetos não é possível. O que você basicamente está tentando fazer é quase

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

O que não é possível, pois o mesmo nome de variável não pode ser reutilizado no C ++.

No entanto, em c ++ 17 , temos if constexpr pelo qual se pode instanciar o único ramo que é verdadeiro no tempo de compilação.

Significando que as soluções possíveis são:

  • Um único modelo variabe lambda. ou
  • Um lambda genérico e encontre o tipo do parâmetro usando decltype para a verificação if constexpr . ( Credits @NathanOliver )

Usando o modelo variabe, você pode fazer algo parecido. ( Veja uma demonstração ao vivo online )

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

e chame assim

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

Usando lambda genérico (desde c ++ 14 ), o acima será: ( Veja uma demonstração ao vivo on-line )

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

e chame o lambda como você faz agora:

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




function-object