为什么当“X”定义为指向函数的转换时,“X x; x();”是允许的,但当它定义为将转换到仿函数时,则不允许?

29
void f(int){}
typedef void (*f_ptr)(int);

struct Functor{
  void operator()(int){}
};

struct X{
  operator f_ptr(){ return f; }
};

struct Y{
  operator Functor(){ return Functor(); }
};

int main(){
  X x; Y y;
  x(5); // works ?!
  y(5); // doesn't ?!
}

点击此处查看在 Ideone 上的实例。输出结果:

错误:没有为‘(Y) (int)’定义匹配的调用

问题1:为什么可以调用 x(5),即使只有 X 定义了转换到函数指针,而没有定义 operator()

问题2:反过来,如果我们定义转换到另一个仿函数,为什么同样的事情不被允许?


14
与C++复杂的转换规则有关。 - Seth Carnegie
1
@Seth:谁能猜到呢。:P - Xeo
1
我只是想让你们知道 :) - Seth Carnegie
1
A: 必定是某些疯狂的边缘情况。无论如何,最好完全避免转换运算符。 - BЈовић
1个回答

25
x(5); // works ?!

这会将 x 隐式转换为一个 f_ptr 并调用它。C++11标准:

§ 13.3.1.1.2 Call to object of class type [over.call.object]

2) In addition, for each non-explicit conversion function declared in T of the form

operator conversion-type-id ( ) attribute-specifier-seqopt cv-qualifier ;

[…where conversion-type-id denotes the type “pointer to function of (P1,...,Pn) returning R”…]


y(5); // doesn't ?!

标准中没有提到关于将类型隐式转换为重载了operator()(也称为函数对象)的类类型,这意味着编译器不允许隐式转换。你必须显式地进行强制类型转换:
static_cast<Functor>(y)(5);

你在 C++ ISO 规范中找到了一种特别允许将类型转换为函数指针但不允许转换为函数对象的语言。这非常有用! - templatetypedef
这并不像我想象中的那么深奥。:) 不过,我在想这是否可以被视为语言缺陷... - Xeo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接