我有以下使用“推断此”模式的代码:
#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
| ^
鉴于此错误,用于“推导此”的基类型是否与使用正常运行时多态性时期望的类型不同?
考虑到编译器生成的错误,用于推论的基类型是否与使用正常运行时多态性时期望的类型不同?
推导出
this
是编译时多态性,就像一般的模板一样。
对于程序中
invoke
的任何给定使用,Self
的类型将从调用的对象表达式中推导出(在编译时),函数 foo
将在该类型中查找,并且仅可以调用该函数。不涉及运行时多态性。对于运行时多态性,您需要 virtual
函数。
当您在类型为
invoke
而不是 base
的表达式上调用 derived
时,则 Self
以及 self
中 invoke
的类型也将是 base
。在 foo
中查找 base
不会找到任何东西,因为你从未在其中声明过 foo
函数。
对于运行时多态性,您需要在
foo
中将 virtual
声明为 base
,然后无论 invoke
是在基类还是派生类型上调用,它都会按照您的预期工作。但是,在这种情况下,该函数根本不需要使用 deduced-this
。普通的非静态成员函数就可以了,就像直接调用 foo
一样,而不是通过 invoke
。