假设我们在全局命名空间中声明了以下lambda:
auto Less = [](int a,int b) -> bool
{
return a < b;
}
Run Code Online (Sandbox Code Playgroud)
以下代码使用了这个lambda:
template<typename T>
struct foo
{
foo(int v){}
bool operator<(const foo<T>&) const
{
return T(1,2);
}
};
int main()
{
typedef foo<decltype(Less)> be_less;
priority_queue<be_less> data;
}
Run Code Online (Sandbox Code Playgroud)
如您所见,我将其Less用作结构的模板参数foo.使用g ++ 4.9.2,此代码无法编译:
test1.cpp:13:21: error: no matching function for call to '<lambda(int, int)>::__lambda0(int, int)'
return T(1,2);
^
test1.cpp:13:21: note: candidates are:
test1.cpp:17:14: note: constexpr<lambda(int, int)>::<lambda>(const<lambda(int, int)>&)
auto Less = [](int a,int b) -> bool
^
test1.cpp:17:14: note: candidate expects 1 argument, 2 provided
test1.cpp:17:14: note: constexpr<lambda(int, int)>::<lambda>(<lambda(int, int)>&&)
test1.cpp:17:14: note: candidate expects 1 argument, 2 provided
Run Code Online (Sandbox Code Playgroud)
我可以解决这个问题,添加两个小的更改,首先我需要将lambda更改为:
bool Less = [](int a,int b) -> bool
{
return a < b;
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的那样,我只是替换auto了bool,单独这个修改仍然不起作用:
test1.cpp:13:21: error: expression list treated as compound expression in functional cast [-fpermiss
ive]
return T(1,2);
Run Code Online (Sandbox Code Playgroud)
除非我添加-fpermissive,否则我可以这样改变operator< bool:
bool operator<(const foo<T>&) const
{
return T((1,2));
}
Run Code Online (Sandbox Code Playgroud)
请注意双括号.现在代码编译,一切正常.
我的问题是,为什么auto Less不工作但bool Less工作的技术原因是什么?
我相信我知道为什么在第二个中需要双括号operator<,这应该是为了避免编译器解释T(1,2)为声明而不是调用.
谢谢你的时间
在你的第一个例子中,你正构建foo<T>在哪里[T = decltype(Less)].所以在这个表达中
return T(1,2);
Run Code Online (Sandbox Code Playgroud)
你试图通过调用一个需要2 int秒的构造函数来构造lambda的一个实例,这显然不存在.这正是错误消息告诉你的
Run Code Online (Sandbox Code Playgroud)error: no matching function for call to '<lambda(int, int)>::__lambda0(int, int)'
唯一存在的构造函数是lambda的复制和移动构造函数(从lambda表达式创建的闭包类型不是默认构造的),编译器尝试匹配参数并且失败
constexpr<lambda(int, int)>::<lambda>(const<lambda(int, int)>&)
constexpr<lambda(int, int)>::<lambda>(<lambda(int, int)>&&)
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)candidate expects 1 argument, 2 provided
在第二种情况下,通过进行此更改
bool Less = [](int a,int b) -> bool
{
return a < b;
};
Run Code Online (Sandbox Code Playgroud)
你所做的是声明一个名为的布尔变量Less并将其初始化为true.
这是因为你拥有的lambda表达式是无捕获的,这意味着它可以隐式转换为一个指向函数的指针,该函数接受与lambda相同的参数operator()并返回与原始lambda相同的类型.所以你将lambda表达式转换为bool(*)(int,int).
接下来,函数指针可以隐式转换为bool并且将始终求值true(假设它实际上指向函数的地址,它在此处执行).所以Less初始化为true.
现在,decltype(Less)只是bool.所以在这里你要尝试一个函数样式转换bool,但传入2个参数
return T(1,2);
Run Code Online (Sandbox Code Playgroud)
因此错误
Run Code Online (Sandbox Code Playgroud)error: expression list treated as compound expression in functional cast
通过添加额外的括号,您有一个由逗号运算符分隔的2个子表达式组成的表达式.这将评估并丢弃第一个子表达式(1)并返回第二个(2)的值,然后将bool其转换为,因此它将转换为true.
我不确定你要做什么才能建议一个解决方案,但是如果你想要的只是为foo那个定义一些比较谓词然后由它调用priority_queue,那么可能以下工作?
struct foo
{
foo(int v) {}
};
auto Less = [](foo const& a, foo const& b) -> bool
{
return true; // do whatever comparison you need
};
int main()
{
using my_priority_queue = std::priority_queue<foo, std::vector<foo>, decltype(Less)>;
my_priority_queue data(Less); // pass a copy of the comparator
}
Run Code Online (Sandbox Code Playgroud)