【问题标题】:Conditional operator can't resolve overloaded member function pointers条件运算符无法解析重载的成员函数指针
【发布时间】:2009-09-14 22:42:32
【问题描述】:

我在处理指向 C++ 中重载成员函数的指针时遇到了一个小问题。以下代码编译正常:

class Foo {
public:
    float X() const;
    void X(const float x);
    float Y() const;
    void Y(const float y);
};

void (Foo::*func)(const float) = &Foo::X;

但这不能编译(编译器抱怨重载不明确):

void (Foo::*func)(const float) = (someCondition ? &Foo::X : &Foo::Y);

想必这和编译器将条件运算符的返回值与函数指针类型分开排序有关吧?我可以解决它,但我很想知道规范如何说所有这些都应该起作用,因为它看起来有点不直观,如果有一些方法可以解决它而不会退回到 5 行 if-then-else .

我正在使用 MSVC++,如果这有什么不同的话。

谢谢!

【问题讨论】:

  • 您应该指出“不起作用”的含义。编译器错误?意外的运行时行为?
  • 已经做到了,谢谢你的建议。

标签: c++ function-pointers conditional-operator


【解决方案1】:

来自第 13.4/1 节(“重载函数的地址,”[over.over]):

使用不带参数的重载函数名称在某些上下文中被解析为函数、指向函数的指针或指向重载集中特定函数的成员函数的指针。函数模板名称被认为是在此类上下文中命名一组重载函数。所选函数的类型与上下文中所需的目标类型相匹配。目标可以是

  • 正在初始化的对象或引用(8.5、8.5.3),
  • 作业的左侧 (5.17),
  • 函数的参数 (5.2.2),
  • 用户定义运算符 (13.5) 的参数,
  • 函数、运算符函数或转换 (6.6.3) 的返回值,或
  • 显式类型转换(5.2.3、5.2.9、5.4)。

重载函数名称前面可以有& 运算符。在未列出的上下文中,重载的函数名称不应在没有参数的情况下使用。 [注意: 任何围绕重载函数名称的冗余括号集都将被忽略 (5.1)。 ]

您希望从上面的列表中选择的目标是第一个,一个正在初始化的对象。但是有一个条件运算符,条件运算符根据其操作数确定其类型,而不是根据任何目标类型。

由于显式类型转换包含在目标列表中,您可以分别对条件表达式中的每个成员指针表达式进行类型转换。我会先做一个 typedef:

typedef void (Foo::* float_func)(const float);
float_func func = (someCondition ? float_func(&Foo::X) : float_func(&Foo::Y));

【讨论】:

    【解决方案2】:

    试试:

        void (Foo::*func1)(const float) = &Foo::X;
        void (Foo::*func2)(const float) = &Foo::Y;
    
        void (Foo::*func3)(const float) = (someCondition ? func1:func2);
    

    问题是三元运算符的结果类型是由它的参数决定的。
    在这种情况下,它无法确定结果类型,因为输入类型有多个选项。直到确定了三元运算符的类型,它才会尝试赋值。

    【讨论】:

      【解决方案3】:

      例子:

      class Foo {
      public:
          void X(float x) {}
          void Y(float y)  {}
          float X() const;
      };
      typedef void (Foo::*Fff)(float);
      Fff func = &Foo::X;
      Fff func2 = true ? (Fff)&Foo::X : (Fff)&Foo::Y;
      
      int main(){
          return 0;
      }
      

      您需要立即强制转换 &Foo::X 以解决重载问题。注意如果你注释掉重载的float X(),你不需要这样做。

      编译器似乎不够聪明,无法推断出三元表达式所需的返回类型(这可能是一个错误)。

      【讨论】:

      • someCondition 不是编译时常量,尽管从我给出的简化示例中这可能并不完全明显。我可以通过模板将其变成一个,但我认为总体上会更丑... :)
      • 不管怎样,它不需要是一个。
      猜你喜欢
      • 2012-01-23
      • 2013-08-18
      • 1970-01-01
      • 2011-06-05
      • 1970-01-01
      • 2014-05-18
      • 1970-01-01
      • 2014-12-24
      相关资源
      最近更新 更多