CRTP:具有基于派生参数的函数

CRTP: function with derived-based argument

本文关键字:派生 参数 函数 于派生 CRTP      更新时间:2023-10-16

下面是我尝试做的一个最低版本:

template<typename D>
struct Base {
void common() {
// ... do something ...
static_cast<D *>(this)->impl();
// ... do something ...
}
void common_with_arg(typename D::Arg arg) {
// ... do something ...
static_cast<D *>(this)->impl_with_arg(arg);
// ... do something more ...
}
};
struct Derived : Base<Derived> {
void impl() { }
using Arg = int;
void impl_with_arg(Arg arg) { }
};

CCD_ 1和CCD_ 2工作正常(如预期)。而Base::common_with_arg()Derived::impl_with_arg()则不然。

例如,使用gcc,我会得到以下错误:

1.cc: In instantiation of ‘struct Base<Derived>’:
1.cc:18:18:   required from here
1.cc:11:7: error: invalid use of incomplete type ‘struct Derived’
void common_with_arg(typename D::Arg arg) {
^~~~~~~~~~~~~~~
1.cc:18:8: note: forward declaration of ‘struct Derived’
struct Derived : Base<Derived> {

直观地(在不了解模板实例化的所有细节的情况下),这似乎是一个合理的错误。是否有其他方法可以实现相同的功能?

void common_with_arg(typename D::Arg arg)
//                            ^^^^^^

您不能在此处访问D::Arg,因为需要Derived的定义。但是该定义永远不可用,因为Base模板正在这里实例化。。。

struct Derived : Base<Derived> { 
//               ^^^^^^^^^^^^^

其中CCD_ 8尚未完全定义。


一种可能的解决方法是将common_with_arg作为函数模板:

template <typename T>
void common_with_arg(T&& arg) {
// ... do something ...
static_cast<D *>(this)->impl_with_arg(std::forward<T>(arg));
// ... do something more ...
}

wandbox上的示例


如果您确实需要Base::common()0类型别名,请阅读以下问题:
"C++静态多态性(CRTP)和使用派生类的typedefs">