重载lambda函数

如何重载简单的本地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。

bozipk 回答:重载lambda函数

不,您不能使lambda超载!

lambda是anonymous functors(即未命名的函数对象),而不是简单的函数。因此,不可能使那些对象过载。 您基本上想做的几乎是

p.2

这是不可能的,因为不能在C ++中重用相同的变量名。


但是,在中,我们拥有if constexpr,通过它可以实例化在编译时唯一的唯一分支。

意味着可能的解决方案是:

  • 一个variabe template lambda。或
  • 通用lambda并使用decltype查找参数的类型 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 检查。(贷方 @NathanOliver

使用variabe template可以执行类似的操作。 See a live demo online

if constexpr

并称呼它

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

使用通用lambda(自起),上述内容将为:See a live demo online

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

并像现在一样调用lambda:

#include <type_traits> // std::is_same_v

constexpr auto translate = [](auto idx) 
{
    if constexpr (std::is_same_v<decltype(idx),0 };
        return table[idx];
    }
    else if constexpr (std::is_same_v<decltype(idx),7} };
        return table[idx];
    }
};
,

Lambda基本上是本地定义函子的语法糖。据我所知,它们永远不会被重载以使用不同的参数来调用。请注意,每个lambda表达式都具有不同的类型,因此即使撇开即时错误,您的代码也无法按预期工作。

但是,您可以定义带有重载operator()的函子。如果可能的话,这将是您从lambda上获得的确切结果。您只是没有简洁的语法。

类似的东西:

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不是函数,它们是带有函数调用运算符的对象。因此,在两个不同的lambda之间不会发生过载。

现在,您可以获得重载解析以使用功能对象,但仅在单个对象的范围内。然后,如果有多个operator(),则可以在它们之间进行重载解析。

但是,λ显然没有办法拥有多个operator()。我们可以编写一个简单的(在中)实用程序类来帮助我们:

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

和推论指南:

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

使用这两个,我们可以重载两个lambda:

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

auto translate_int = [](int idx){
    constexpr static int table[8] {7,0};
    return table[idx];
};

auto translate_char = [](char c) {
    std::map<char,int> table { {'a',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 ++功能相匹配的解决方案就不难了。

本文链接:https://www.f2er.com/3163955.html

大家都在问