这是对这个问题的后续:为什么我可以调用一个 const 引用的可调用函数,而实际的可调用函数是一个可变的 lambda?
当像这样调用时,我可以模仿 const 可变闭包到函数指针的隐式转换:
#include <iostream>
void dummy() { std::cout << "call dummy\n";}
using fptr = void(*)();
struct callable {
void operator()() {std::cout << "call callable\n"; }
operator fptr() const {
std::cout << "convert\n";
return &dummy;
}
};
int main()
{
auto exec = []( auto const &fn ) {
std::cout << "call\n";
fn();
};
exec( callable{} );
}
我不明白为什么会触发隐式转换。它在传递参数时不会发生(参数是推导出来的,因此不考虑隐式转换),而仅在()
调用时才会发生,正如输出所示:
call
convert
call dummy
我尝试进行实验来了解发生了什么。尝试使用其他运算符进行类似操作,但没有成功(正如预期的那样):
#include <iostream>
struct bar {
void operator+(int) const { std::cout << "bar\n"; };
};
struct foo {
void operator+(int) { std::cout << "foo\n"; }
operator bar() const { return {}; }
};
int main() {
auto exec = []( auto const &fn ) {
std::cout << "call\n";
fn + 42;
};
exec(foo{});
};
错误:
<source>:15:12: error: passing 'const foo' as 'this' argument discards qualifiers [-fpermissive]
15 | fn + 42;
| ~~~^~~~
调用运算符有什么特殊之处?它怎么可能fn()
隐式转换fn
为调用其他函数呢?
PS:同时我发现它一定与转换为函数指针有关,因为当我将第一个例子转换为比第二个更相似的例子时,我得到了预期的错误:
#include <iostream>
struct foo {
void operator()() const { std::cout << "call foo\n"; }
};
struct callable {
void operator()() {std::cout << "call callable\n"; }
operator foo() const { return {}; };
};
int main()
{
auto exec = []( auto const &fn ) {
std::cout << "call\n";
fn();
};
exec( callable{} );
}
现在我得到了预期的错误
<source>:17:11: error: no match for call to '(const callable) ()'
17 | fn();
| ~~^~
现在的问题是:转换为函数指针类型有什么特殊之处?
看起来它fn()
考虑了函数指针的转换。为什么?