解决通过“推导此”引用调用大多数派生方法时的编译器错误

问题描述 投票:0回答:1

我有以下使用“推断此”模式的代码:

#include <print>

struct base
{
   template <typename Self>
   void invoke(this Self& self)
   {
      self.foo();
   }
};

struct derived : base
{
   void foo() { std::println("derived::foo()"); }
};

int main()
{
   derived d;
   d.invoke(); // ok

   base& bref = d;
   bref.invoke(); // error

   base* bptr = &d;
   bptr->invoke(); // error

   return 0;
}

编译器生成以下错误:

<source>:8:12: error: no member named 'foo' in 'base'
    8 |       self.foo();
      |       ~~~~ ^
<source>:23:6: note: in instantiation of function template specialization 'base::invoke<base>' requested here
   23 |    bref.invoke(); // error
      |      ^

鉴于此错误,用于“推导此”的基类型是否与使用正常运行时多态性时期望的类型不同?

c++ this
1个回答
1
投票

考虑到编译器生成的错误,用于推论的基类型是否与使用正常运行时多态性时期望的类型不同?

推导出

this
编译时多态性,就像一般的模板一样。

对于程序中

invoke
的任何给定使用,
Self
的类型将从调用的对象表达式中推导出(在编译时),函数
foo
将在该类型中查找,并且仅可以调用该函数。不涉及运行时多态性。对于运行时多态性,您需要
virtual
函数。

当您在类型为

invoke
而不是
base
的表达式上调用
derived
时,则
Self
以及
self
invoke
的类型也将是
base
。在
foo
中查找
base
不会找到任何东西,因为你从未在其中声明过
foo
函数。

对于运行时多态性,您需要在

foo
中将
virtual
声明为
base
,然后无论
invoke
是在基类还是派生类型上调用,它都会按照您的预期工作。但是,在这种情况下,该函数根本不需要使用 deduced-
this
。普通的非静态成员函数就可以了,就像直接调用
foo
一样,而不是通过
invoke

© www.soinside.com 2019 - 2024. All rights reserved.