用运行时常量实例化的功能模板

时间:2019-03-25 09:37:02

标签: c++ templates lambda function-templates

我需要某种方法来结合lambda捕获运行时值的能力和函数模板指定我们想要的任何类型的能力。最好的方法是什么?

Lambda允许我们在运行时捕获局部变量的值,例如

unsigned char c=0;
auto compareEquality=[c](unsigned char c1) ->bool {return c1==c;};
..
scanner(compareEquality);

因此scanner传递了一个函数,该函数嵌入了运行时确定值0,在scanner内我们调用compareEquality传递了一个unsigned char来与0或任何其他值进行比较在运行时获得的值。但是我也希望参数可以是我想要的任何类型,而不仅仅是unsigned char。拥有这个会很好:

template<typename T>
bool compareEquality(T data) {
  return ( data== c);//error, what is 'c'?
}

但是使用函数模板,我无法在其中嵌入运行时常量,而只能像这样传递函数:

scanner(compareEquality);

上面的代码不允许我在函数内部指定要与之比较的值。

将函数模板和lambda的捕获结合在一起的最佳方法是什么,以便compareEquality可以与某个嵌入式运行时值一起传递,而不必定义接受不同参数类型的单独版本。

2 个答案:

答案 0 :(得分:1)

我可能误解了您的问题,但是您可以编写一个返回lambda的高阶函数:

#include <iostream>
#include <vector>
#include <algorithm>

template <typename T>
constexpr auto is_equal_to(T value)
{
    return [value](T const& x) { return x == value; };   
}

int main(void)
{
    std::vector src {17, 4, 42, 23, 9, 17, 8, 61};   
    int x;
    std::cin >> x;
    std::cout << "count (" << x << "): "
        << std::count_if(src.cbegin(), src.cend(), is_equal_to(x)) << '\n';

    std::cout << "count (42): "
        << std::count_if(src.cbegin(), src.cend(), is_equal_to(42)) << '\n';   
}

答案 1 :(得分:1)

您可以做的是拥有一个为您构建这些lambda的函数,如下所示:

template<typename T>
auto ret_f(const T& p){
    return  [p](const T& p1)-> bool 
               {return p1==p;};
}
struct foo{
    int a;
    double b;
    bool c;

    bool operator==(const foo& f){
        return false;
    }
};

int main() { 
    unsigned char c= 0;
    int i = 0;
    foo bar {22,15.2,false};

    auto fchar = ret_f(c);
    auto fint = ret_f(i);    
    auto f_foo = ret_f(bar);

    cout<<fchar('a');

    cout<<fint(2.6);

    cout<<f_foo(bar);

return 0;

这样,您可以简单地使用正确的参数调用ret_f并返回正确的lambda。