Lambda 作为模板参数
Lambda as template parameter
我发现了那些类似的问题 Lambda expressions as class template parameters and How to use a lambda expression as a template parameter?,但即使有了可用的答案,我还是不明白为什么以下代码不起作用(g++4.8.2 和 g++-4.9):
auto GoLess = [](int a,int b) -> bool
{
return a < b;
};
template<typename Order>
struct foo
{
int val;
bool operator<(const foo& other)
{
return Order(val, other.val);
}
};
typedef foo<decltype(GoLess)> foo_t;
int main()
{
foo_t a,b;
bool r = a < b;
}
编译器输出为:
test.cpp: In instantiation of ‘bool foo<Order>::operator<(const foo<Order>&) [with Order = <lambda(int, int)>]’:
test.cpp:26:15: required from here
test.cpp:17:30: error: no matching function for call to ‘<lambda(int, int)>::__lambda0(int&, const int&)’
return Order(val, other.val);
^
test.cpp:17:30: note: candidates are:
test.cpp:5:16: note: constexpr<lambda(int, int)>::<lambda>(const<lambda(int, int)>&)
auto GoLess = [](int a,int b) -> bool
^
test.cpp:5:16: note: candidate expects 1 argument, 2 provided
test.cpp:5:16: note: constexpr<lambda(int, int)>::<lambda>(<lambda(int, int)>&&)
test.cpp:5:16: note: candidate expects 1 argument, 2 provided
这段代码不应该起作用吗?从我理解的那些其他线程中读取这段代码应该编译,但不是。
非常感谢
附录:
为了澄清一点,在上述问题中,KennyTM 编写了以下代码:
auto comp = [](const A& lhs, const A& rhs) -> bool { return lhs.x < rhs.x; };
auto SetOfA = std::set <A, decltype(comp)> (comp);
这应该有效,std::set 的第二个参数是 'comparator',在本例中是 lambda,在我的代码中,我正在尝试做同样的事情,或者至少我认为我正在做同样的事情,但我的代码不起作用。我的代码中缺少什么?
请注意 Lambda expressions as class template parameters
中的 Xeo
auto my_comp = [](const std::string& left, const std::string& right) -> bool {
// whatever
}
typedef std::unordered_map<
std::string,
std::string,
std::hash<std::string>,
decltype(my_comp)
> map_type;
这应该又可以了。我的错在哪里?
谢谢
正如编译器告诉您的那样,问题出在这一行:
return Order(val, other.val);
因为 Order
是一个类型(并且 不是 一个函数),这就是调用 Order 的双参数构造函数。但是它没有。
调用函数 class 的正确语法是:
return Order()(val, other.val);
但是,这也行不通,因为为 lambda 生成的 class 具有已删除的默认构造函数。
简而言之,您需要使用(唯一的)lambda 实例来实例化您的 class。
这是一种可能的处理方式:
template<typename Order>
struct foo {
foo(Order compare) : compare_(compare) {}
bool operator<(const foo& other) {
return compare_(val, other.val);
}
int val;
Order compare_;
};
/* In practice, you'll want to template a parameter pack
* for the other arguments to the constructor, since those are likely.
* Also, you might want to use std::forward.
*/
template<typename Order>
foo<Order> foomaker(Order order) {
return foo<Order>(order);
}
int main() {
auto GoLess = [](int a,int b) -> bool
{
return a < b;
};
auto a = foomaker(GoLess);
auto b = foomaker(GoLess);
bool r = a < b;
return r;
}
我发现了那些类似的问题 Lambda expressions as class template parameters and How to use a lambda expression as a template parameter?,但即使有了可用的答案,我还是不明白为什么以下代码不起作用(g++4.8.2 和 g++-4.9):
auto GoLess = [](int a,int b) -> bool
{
return a < b;
};
template<typename Order>
struct foo
{
int val;
bool operator<(const foo& other)
{
return Order(val, other.val);
}
};
typedef foo<decltype(GoLess)> foo_t;
int main()
{
foo_t a,b;
bool r = a < b;
}
编译器输出为:
test.cpp: In instantiation of ‘bool foo<Order>::operator<(const foo<Order>&) [with Order = <lambda(int, int)>]’:
test.cpp:26:15: required from here
test.cpp:17:30: error: no matching function for call to ‘<lambda(int, int)>::__lambda0(int&, const int&)’
return Order(val, other.val);
^
test.cpp:17:30: note: candidates are:
test.cpp:5:16: note: constexpr<lambda(int, int)>::<lambda>(const<lambda(int, int)>&)
auto GoLess = [](int a,int b) -> bool
^
test.cpp:5:16: note: candidate expects 1 argument, 2 provided
test.cpp:5:16: note: constexpr<lambda(int, int)>::<lambda>(<lambda(int, int)>&&)
test.cpp:5:16: note: candidate expects 1 argument, 2 provided
这段代码不应该起作用吗?从我理解的那些其他线程中读取这段代码应该编译,但不是。
非常感谢
附录:
为了澄清一点,在上述问题中,KennyTM 编写了以下代码:
auto comp = [](const A& lhs, const A& rhs) -> bool { return lhs.x < rhs.x; };
auto SetOfA = std::set <A, decltype(comp)> (comp);
这应该有效,std::set 的第二个参数是 'comparator',在本例中是 lambda,在我的代码中,我正在尝试做同样的事情,或者至少我认为我正在做同样的事情,但我的代码不起作用。我的代码中缺少什么?
请注意 Lambda expressions as class template parameters
中的 Xeoauto my_comp = [](const std::string& left, const std::string& right) -> bool {
// whatever
}
typedef std::unordered_map<
std::string,
std::string,
std::hash<std::string>,
decltype(my_comp)
> map_type;
这应该又可以了。我的错在哪里?
谢谢
正如编译器告诉您的那样,问题出在这一行:
return Order(val, other.val);
因为 Order
是一个类型(并且 不是 一个函数),这就是调用 Order 的双参数构造函数。但是它没有。
调用函数 class 的正确语法是:
return Order()(val, other.val);
但是,这也行不通,因为为 lambda 生成的 class 具有已删除的默认构造函数。
简而言之,您需要使用(唯一的)lambda 实例来实例化您的 class。
这是一种可能的处理方式:
template<typename Order>
struct foo {
foo(Order compare) : compare_(compare) {}
bool operator<(const foo& other) {
return compare_(val, other.val);
}
int val;
Order compare_;
};
/* In practice, you'll want to template a parameter pack
* for the other arguments to the constructor, since those are likely.
* Also, you might want to use std::forward.
*/
template<typename Order>
foo<Order> foomaker(Order order) {
return foo<Order>(order);
}
int main() {
auto GoLess = [](int a,int b) -> bool
{
return a < b;
};
auto a = foomaker(GoLess);
auto b = foomaker(GoLess);
bool r = a < b;
return r;
}