C++具有自定义初始化的静态调度
C++ static dispatch with custom initialization
我想将CRTP用于代码中对性能敏感的部分。但是,我的基类有一个位集,其大小取决于派生类。我希望这样的事情会起作用:
template <typename Derived>
class Base {
protected:
std::bitset<Derived::bsize> data_;
};
class Foo : public Base<Foo> {
public:
constexpr static size_t bsize = 2;
};
但编译器抱怨:"Foo中没有成员bsize"。我想我可以通过在基类中模板化位集长度来解决我的问题:
template <typename Derived, size_t size>
class Base {
protected:
std::bitset<size> data_;
};
class Foo : public Base<Foo,2> { ... };
将来,我可能希望使用更复杂的表达式来计算位集长度。有没有办法使用 constexpr 函数完成工作?(在精神上更接近我的第一个非工作解决方案) 谢谢。
答案是:你不能在C++中使用CRTP执行此操作。正在发生的事情是,当Base<Foo>
被实例化时,Foo::bsize
还不存在。这是因为当编译器在Foo
类上看到Base<Foo>
时,就会发生这种情况,该类位于您的{
之前。事情并没有那么简单,但这是一般的想法。
这里有一种解决方法可以执行您想要的操作,即将所有必要的信息捆绑在一个类中,然后将其作为模板参数提供。我不知道这个模式的名称(我见过"行李类",但这感觉很贬义),但你可以在标准库中找到这样的例子,比如std::char_traits
。
class FooTraits {
constexpr static size_t bsize = 2;
};
template <class Traits = FooTraits>
class BasicFoo {
protected:
std::bitset<Traits::bsize> data_;
};
特征非常灵活 - 您可以将static constexpr
函数放入FooTraits
中以计算您需要的任何内容。在您的情况下,派生类会将派生类型特定的FooTraits
版本传递给BasicFoo
的Traits
模板参数。
值得注意的是,您的里程可能会有所不同。虽然灵活,但特征的问题在于,想要实现FooTraits
概念的人需要确保他们实现BasicFoo
需要的所有东西,否则他们将得到一个可怕的编译错误(在 C++20 中,这是通过概念帮助的)。如果不仔细考虑,特质可能会成为事物的倾倒场,这使得实施替代方案FooTraits
变得更加困难。
- C++ 模板中的静态常量初始化顺序
- C++模板类静态成员初始化
- 类静态变量初始化顺序
- 类中的静态 constexpr 初始化链
- C :(不重复)积分静态成员初始化(不仅是声明!),导致链接器错误,原因
- C 语言中的静态变量初始化
- 使用静态方法初始化 const 类字段的做法是好是坏
- 共享库中 __attribute__((构造函数)) 的全局/静态变量初始化问题
- C++函数中的多线程静态 POD 初始化
- 类静态变量初始化的规则是什么?
- 向模板化静态成员初始化添加和不添加'typename'都会出错
- 使用静态常量初始化unique_ptr时出现未定义的引用错误
- C++中重复静态变量初始化
- 模板类中的静态成员初始化
- 静态成员的静态阵列:初始化顺序惨败的可能性
- 模板专用化和静态成员初始化
- 静态变量初始化的线程安全性
- C++模板函数中的静态变量初始化
- 非静态成员变量的静态变量初始化
- 我可以在C 中更改静态变量初始化顺序吗?