C++中隐式转换可以访问的调用成员函数

mlmc2os5  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(112)

尝试创建一个类似于std::reference_wrapper的引用 Package 器,但可以调用 Package 对象的方法。

#include <iostream>

class A {
public:
    void f() {
         std::cout << "A::f()\n";
    }
};

class WrapA {
public:
    WrapA(A& a) : _a_ptr{&a} {}

    operator A&() {
        return *_a_ptr;
    }
private:
    A* _a_ptr;
};

int main() {
    A a;
    WrapA wrap{a};

    wrap.f();                  // Fails with compile error: ‘class WrapA’ has no member named ‘f’
    static_cast<A>(wrap).f();  // Works

    return 0;
}

为什么在 Package 器对象上调用类A函数f()不起作用,尽管从WrapA到A的隐式转换是可能的?有没有办法解决这个问题?
尝试使用std::reference_wrapper,但失败并出现相同的编译错误。

ffx8fchx

ffx8fchx1#

获得这种行为的一种方法是重载箭头操作符operator ->,并让它返回指向 Package 对象的指针。它将被编译器递归地应用到返回的指针上,并允许您调用成员函数。那会给你给予

#include <iostream>

class A {
public:
    void f() {
         std::cout << "A::f()\n";
    }
};

class WrapA {
public:
    WrapA(A& a) : _a_ptr{&a} {}

    A* operator ->() {
        return _a_ptr;
    }
private:
    A* _a_ptr;
};

int main() {
    A a;
    WrapA wrap{a};

    wrap->f();
    
    return 0;
}

其输出

A::f()

你可以看到它在这个live example中工作。

5lwkijsr

5lwkijsr2#

你问
为什么在 Package 器对象上调用类A函数f()不起作用,尽管从WrapA到A的隐式转换是可能的?
该标准指定了可以进行隐式转换的上下文(https://timsong-cpp.github.io/cppwp/n4140/conv#2):
2 [ * 注意 *:在以下几种情况下,具有给定类型的表达式将隐式转换为其他类型:
(2.1)--当用作操作符的操作数时。操作符对其操作数的要求决定了目标类型(Clause [expr])。
(2.2)--在if语句或迭代语句的条件下使用时([stmt.select],[stmt.iter])。目标类型为bool。
(2.3)--在switch语句的表达式中使用时。目的地类型为整数([stmt.select])。
(2.4)--当用作初始化的源表达式时(包括用作函数调用中的参数和用作返回语句中的表达式)。被初始化的实体的类型(通常)是目标类型。参见[dcl.init]、[dcl.init.ref]。

    • 结束注解 * ]
      请注意,在点运算符中使用对象不是其中之一。

相关问题