c++ - CRTP:将类型从派生类传递到基类
问题描述
在CRTP中,基类可以使用派生类中的函数和变量。但是,派生类的类型不能被基类直接使用,见下面的代码:
#include <iostream>
template <class Derived>
class A {
public:
//using Scalar = typename Derived::Scalar; // Error!
static constexpr int NA1 = Derived::NB1;
static constexpr int NA2 = Derived::NB2;
static constexpr int NA3 = Derived::NB3;
};
template <int _N = 2>
class B : public A<B<_N>> {
public:
using Scalar = double;
static constexpr int NB1 = 1;
static constexpr int NB2 = _N;
static constexpr int NB3 { sizeof(Scalar) };
};
int main(int argc, char** argv)
{
using Type = B<2>;
std::cout << Type::NA1 << ' '
<< Type::NA2 << ' '
<< Type::NA3 << '\n';
}
// output:
// 1 2 8
如果该行using Scalar = typename Derived::Scalar;
未注释,则会发生错误:
main.cpp:6:11: error: invalid use of incomplete type 'class B<2>'
我知道类型(Scalar
)可以作为模板参数传递给基类,但是为什么不能像变量一样使用呢?这只是语言规则吗?或者是否有任何逻辑限制使其无法实施?
解决方案
Inside A
,B
是一个不完整的类型 - 编译器还没有看到 的完整声明B
,所以你不能Scalar
在A
. 这是一种自然的限制。
您的示例中类型和标量之间的区别在于,初始化的实例化NA
不是在声明时发生,而是在B
编译器看到之后(并成为完整类型)。
让我们更改代码并强制编译器NA
在类声明中使用值:
template <class Derived>
class A {
public:
static constexpr int NA1 = Derived::NB1;
std::array<int, NA1> foo();
};
现在你会得到基本上相同的错误:
<source>:8:41: error: incomplete type 'B<2>' used in nested name specifier
8 | static constexpr int NA1 = Derived::NB1;
| ^~~
这类似于成员函数:您不能在其声明中使用 CRTP 基类型,但您可以在其主体中使用该类型:
void foo() {
std::array<int, NA1> arr;
// ...
}
将编译,因为实例化发生在基类已经是完整类型的地方。
推荐阅读
- php - php strtotime '第三天 + 1 个月' = false
- r - 如何解决 r 中弹性包中的“curl 中的错误:Broken pipe”
- javascript - 如何将 Dialog 组件添加到 BottomNavigation
- data-vault - Data Vault 将多个集线器连接成链接,是使用一个链接的最佳方式,还是拆分链接始终是 Data Vault 中的好方法?
- javascript - 我们如何一个一个地提取数字?
- html - 如何为html中的链接配置嵌套路径
- javascript - 下拉单击禁用悬停并在悬停时触发 JS 功能
- javascript - 双间隔调用,它不应该在 node.js 中
- reactjs - 我想将后端代码(即rest api)集成到前端reactjs代码
- google-assistant-sdk - 是否有任何付款方式可根据要求增加特定项目/用户的 google-assistant-sdk 配额限制?