在c++ 11中,是否有一种方法来模板lambda函数?还是它本身就太具体了,无法被模板化?

我知道我可以定义一个经典的模板化类/函子,但问题更像是:语言是否允许模板化lambda函数?


当前回答

我一直在使用最新的clang版本5.0.1,使用-std=c++17标记进行编译,现在对lambdas的自动类型参数提供了一些很好的支持:

#include <iostream>
#include <vector>
#include <stdexcept>

int main() {
    auto slice = [](auto input, int beg, int end) {
        using T = decltype(input);
        const auto size = input.size();
        if (beg > size || end > size || beg < 0 || end < 0) {
            throw std::out_of_range("beg/end must be between [0, input.size())");
        }
        if (beg > end) {
            throw std::invalid_argument("beg must be less than end");
        }
        return T(input.begin() + beg, input.begin() + end);
    };
    auto v = std::vector<int> { 1,2,3,4,5 };
    for (auto e : slice(v, 1, 4)) {
        std::cout << e << " ";
    }
    std::cout << std::endl;
}

其他回答

c++ 11 lambda不能像其他答案中所述的那样被模板化,但当在模板化的类或函数中使用lambda时,decltype()似乎有所帮助。

#include <iostream>
#include <string>

using namespace std;

template<typename T>
void boring_template_fn(T t){
    auto identity = [](decltype(t) t){ return t;};
    std::cout << identity(t) << std::endl;
}

int main(int argc, char *argv[]) {
    std::string s("My string");
    boring_template_fn(s);
    boring_template_fn(1024);
    boring_template_fn(true);
}

打印:

My string
1024
1

我发现这种技术在处理模板化代码时很有帮助,但意识到它仍然意味着lambdas本身不能被模板化。

在c++ 20中,可以使用以下语法:

auto lambda = []<typename T>(T t){
    // do something
};

我一直在使用最新的clang版本5.0.1,使用-std=c++17标记进行编译,现在对lambdas的自动类型参数提供了一些很好的支持:

#include <iostream>
#include <vector>
#include <stdexcept>

int main() {
    auto slice = [](auto input, int beg, int end) {
        using T = decltype(input);
        const auto size = input.size();
        if (beg > size || end > size || beg < 0 || end < 0) {
            throw std::out_of_range("beg/end must be between [0, input.size())");
        }
        if (beg > end) {
            throw std::invalid_argument("beg must be less than end");
        }
        return T(input.begin() + beg, input.begin() + end);
    };
    auto v = std::vector<int> { 1,2,3,4,5 };
    for (auto e : slice(v, 1, 4)) {
        std::cout << e << " ";
    }
    std::cout << std::endl;
}

更新2018:c++ 20将带来模板化和概念化的lambdas。该特性已经集成到标准草案中。


更新2014:c++ 14已于今年发布,现在提供了与本例相同语法的多态lambdas。一些主要的编译器已经实现了它。


在c++ 11中,遗憾的是没有。多态lambdas在灵活性和功能方面非常出色。

它们最终变成单形的最初原因是因为概念。概念使这种代码情况变得困难:

template <Constraint T>
void foo(T x)
{
    auto bar = [](auto x){}; // imaginary syntax
}

在一个受约束的模板中,只能调用其他受约束的模板。(否则约束将无法检查。)foo可以调用bar(x)吗?lambda有什么约束(毕竟它的参数只是一个模板)?

概念还没有准备好解决这类问题;它需要更多的东西,比如late_check(概念直到调用才被检查)等等。更简单的方法是放弃所有这些,坚持用单形。

然而,随着c++ 0x中概念的移除,多态lambda又变成了一个简单的命题。但是,我找不到任何建议。:(

在c++ 11中,lambda函数不能被模板化,但是在下一个版本的ISO c++标准(通常称为c++ 14)中,将引入这个特性。(来源)

使用的例子:

auto get_container_size = [] (auto container) { return container.size(); };

注意,尽管语法使用了关键字auto,但类型推导不会使用auto类型推导的规则,而是使用模板参数推导的规则。另请参阅通用lambda表达式的建议(以及对此的更新)。