C++ C++;带有自定义初始化的静态分派

C++ C++;带有自定义初始化的静态分派,c++,static,bitset,dispatch,crtp,C++,Static,Bitset,Dispatch,Crtp,我想将CRTP用于代码中对性能敏感的部分。但是,我的基类有一个位集,其大小取决于派生类。我希望这样的事情能奏效: template <typename Derived> class Base { protected: std::bitset<Derived::bsize> data_; }; class Foo : public Base<Foo> { public: constexpr static size_t bsize = 2; };

我想将CRTP用于代码中对性能敏感的部分。但是,我的基类有一个位集,其大小取决于派生类。我希望这样的事情能奏效:

template <typename Derived>
class Base {
protected:
    std::bitset<Derived::bsize> data_;
};

class Foo : public Base<Foo> {
public:
    constexpr static size_t bsize = 2;
};
模板
阶级基础{
受保护的:
std::位集数据;
};
Foo类:公共基础{
公众:
constexpr静态大小=2;
};
但编译器抱怨:“Foo中没有成员bsize”。我想我也可以通过在基类中模板化位集长度来解决我的问题:

template <typename Derived, size_t size>
class Base {
protected:
    std::bitset<size> data_;
};

class Foo : public Base<Foo,2> { ... };
模板
阶级基础{
受保护的:
std::位集数据;
};
Foo类:公共基{…};
将来,我可能希望使用更复杂的表达式来计算位集长度。有没有办法使用constexpr函数完成任务?(精神上更接近我的第一个非工作解决方案)
谢谢。

< P>答案是:C++中不能用CRTP来实现这一点。当
Base
被实例化时,
Foo::bsize
还不存在。这是因为编译器在
Foo
类上看到
Base
时会发生这种情况,它位于
{
之前

这里有一个解决方法可以实现您想要的功能,即将所有必要的信息捆绑在一个类中,然后将其作为模板参数提供。我不知道此模式的名称(我见过“baggage class”,但这感觉有些贬义),但您可以在标准库中找到此类示例,例如

class脚踏板{
constexpr静态大小=2;
};
模板
类BasicFoo{
受保护的:
std::位集数据;
};
Traits非常灵活——您只需将
static constexpr
函数放入
FooTraits
中,即可计算所需的任何内容。在您的情况下,派生类将
FooTraits
的派生类型特定版本传递给
BasicFoo
Traits
模板参数

值得注意的是,你的理解可能会有所不同。虽然灵活,但traits的问题在于,想要实现
FooTraits
概念的人需要确保他们实现了
BasicFoo
所需的所有东西,否则他们会遇到可怕的编译错误(在C++20中,这是通过.如果不仔细考虑,特性可能会成为一个垃圾场,这使得实现另一种
FooTraits
更加困难

class FooTraits {
    constexpr static size_t bsize = 2;
};

template <class Traits = FooTraits>
class BasicFoo {
protected:
    std::bitset<Traits::bsize> data_;
};