代码之家  ›  专栏  ›  技术社区  ›  user283145

如何使用lambda表达式作为模板参数?

  •  32
  • user283145  · 技术社区  · 14 年前

    如何使用lambda表达式作为模板参数?例如,作为初始化类:STD::SET的比较类。

    下面的解决方案应该有效,因为lambda表达式只创建一个匿名结构,该结构应该适合作为模板参数。但是,会产生很多错误。

    代码示例:

    struct A {int x; int y;};
    std::set <A, [](const A lhs, const A &rhs) ->bool {
        return lhs.x < rhs.x;
        } > SetOfA;
    

    错误输出(我使用g++4.5.1编译器和-STD= C++0x编译标志):

    error: ‘lhs’ cannot appear in a constant-expression
    error: ‘.’ cannot appear in a constant-expression
    error: ‘rhs’ cannot appear in a constant-expression
    error: ‘.’ cannot appear in a constant-expression
    At global scope:
    error: template argument 2 is invalid
    

    这是GCC中的预期行为还是错误?

    编辑

    正如有人指出的,当lambda表达式返回 实例 它们所引用的匿名结构的。

    但是,修复该错误并不能解决问题。我得到 lambda-expression in unevaluated context 以下代码错误:

    struct A {int x; int y;};
    typedef decltype ([](const A lhs, const A &rhs) ->bool {
        return lhs.x < rhs.x;
        }) Comp;
    std::set <A, Comp > SetOfA;
    
    4 回复  |  直到 8 年前
        1
  •  33
  •   kennytm    14 年前

    的第二个模板参数 std::set 期望 类型 ,不是 表达 所以只是你用错了。

    您可以这样创建集合:

    auto comp = [](const A& lhs, const A& rhs) -> bool { return lhs.x < rhs.x; };
    auto SetOfA = std::set <A, decltype(comp)> (comp);
    
        2
  •  4
  •   Roger Pate    14 年前

    对于使用这种方式的比较器,使用非0x方法仍然更好:

    struct A { int x; int y; };
    
    struct cmp_by_x {
      bool operator()(A const &a, A const &b) {
        return a.x < b.x;
      }
    };
    
    std::set<A, cmp_by_x> set_of_a;
    

    但是,在0x中,当当前的C++被禁止时,可以使CMPYBYYX成为本地类型(即在函数内定义它)。

    此外,您的比较将a(x=1,y=1)和a(x=1,y=2)视为等效项。如果不需要,则需要包括有助于唯一性的其他值:

    struct cmp_by_x {
      bool operator()(A const &a, A const &b) {
        return a.x < b.x || (a.x == b.x && a.y < b.y);
      }
    };
    
        3
  •  1
  •   towi    8 年前

    不确定这是否是您要求的,但是返回rettype并接受intype的lambda的签名将是:

    std::function<RetType(InType)>
    

    (确保 #include <functional> )

    您可以通过使用typedef来缩短它,但我不确定您是否可以使用decltype来避免弄清楚实际的类型(因为lambdas显然不能在该上下文中使用)。

    所以typedef应该是:

    typedef std::function<bool(const A &lhs, const A &rhs)> Comp
    

    using Comp = std::function<bool(const A &lhs, const A &rhs)>;
    
        4
  •  0
  •   yaron kahanovitch    9 年前

    问题是最后一个模板参数的类型不是对象,因此您可能需要执行以下操作

        std::set <A, std::fuction<bool(const A &,const A &)>> 
                  SetOfA([](const A lhs, const A &rhs) ->bool {
                                                                 return lhs.x < rhs.x;
                                                              } > SetOfA;
    

    要使其更简单,可以执行以下操作:

    auto func = SetOfA([](const A lhs, const A &rhs) ->bool { return lhs.x < rhs.x;}
    set <A,decltype(func)> SetOfA(func);
    

    干杯