奇怪的重复模板模式(CRTP)是一种C ++习语,其中类X派生自使用X本身作为模板参数的类模板实例化。
例如,我可以使用 CRTP 执行以下操作: 模板 结构可共享{ 整数计数=0; 模板 静态自*创建(参数&&...
我有一个静态的硬编码测试代码。之后我将其转换为动态绑定来测试性能,虚拟调用似乎慢了大约两倍。 #包括 我有一个静态的硬编码测试代码。之后我将其转换为动态绑定来测试性能,虚拟调用似乎慢了大约两倍。 #include <vector> class vUnit { public: virtual ~vUnit() {;} virtual float process(float f) = 0; }; class vRack { public: vRack() {;} ~vRack() {;} inline void addUnit(vUnit* unit_ptr) { _units.push_back(unit_ptr); } inline float process_all(float f) { float res = 0.; for (int j = 0 ; j< 60; j++) { for (auto u : _units) { f = u->process(f); } } res += f; return res; } private: std::vector<vUnit*> _units ; int _i = 0; }; class vMultiplyF : public vUnit { public: vMultiplyF(float v) {_f = v;} inline float process(float f) final { return f * _f; } private: float _f; }; class vDivideF : public vUnit { public: vDivideF(float v) {_f = v;} inline float process(float f) final { if (f > 0) { return _f / f; } else return 0.0f; } private: float _f; }; int main () { float f = 1.5f, r = 0.0f; vRack vR; vMultiplyF vM(5.1f); vDivideF vD(5.5f); vR.addUnit(&vM); vR.addUnit(&vD); for( int i = 0 ; i < 1000 ; i++) { f = vR.process_all(f); r += f; } return 0; } 我认为 CRTP 可能是一个合理的妥协,但我不太明白如何重写 vRack.addUnit(),以便它可以采用不同的 vUnit 实现。有人可以帮忙吗? 我认为 CRTP 可能是一个合理的妥协。 CRTP 在这里帮不了你。您需要一些间接来区分不同的操作。 如果配置是静态的,那么您可以从迭代 vUnit 的容器切换为使用折叠表达式来组合特定对象的元组。 #include <tuple> template <typename T> concept Unit = requires(T unit, float f) { f = unit.process(f); }; class vMultiplyF { // No base class needed public: vMultiplyF(float v) {_f = v;} float process(float f) { return f * _f; } private: float _f; }; class vDivideF { // No base class needed public: vDivideF(float v) {_f = v;} float process(float f) { if (f > 0) { return _f / f; } else return 0.0f; } private: float _f; }; template <Unit... Units> class vRack { public: vRack(Units... units) : _units(std::move(units)...) {} float process_all(float f) { for (int j = 0 ; j< 60; j++) { // evaluates (f = unit.process(f)) for each unit in sequence std::apply([&](Units&... unit){ ((f = unit.process(f)), ...); }, _units); } return f; } private: std::tuple<Units...> _units; }; int main () { float f = 1.5f, r = 0.0f; vMultiplyF vM(5.1f); vDivideF vD(5.5f); vRack vR(vM, vD); // deduces vRack<vMultiplyF, vDivideF> for( int i = 0 ; i < 1000 ; i++) { f = vR.process_all(f); r += f; } return 0; }
相关问题:一、二 经过几天的尝试了解CRTP,现在看来我的理解比以前还少了:) 考虑以下代码: #包括 模板...
有一个基类Base,它有很多功能,并且可以/应该按原样使用。但我想用(几个)派生类来扩展它,而不用一个 bu...
我试图编写一个可以使用 CRTP 注册类型的工厂,就像这个问题一样,但我遇到了一些问题。 #包括 #包括 #包括
举一个简单的CRTP例子: 模板 静态可调用结构体 { 静态自动静态调用() { 返回 Target().Call(); } 使用 ReturnType = decltype(Target()....
在C++中,相比于final或者非虚函数,CRTP有什么优势?
我是学习现代 C++ 编程的新手。我读过很多博客和问题,但没有找到这个问题的答案。在C++中,相比于final或者非虚函数,有什么优势...
我是 CRTP 和大量模板化代码的新手,所以我不确定这是否可能...... 我有一个模板类如下: 模板 类基本类型组件 { 民众: 模板...
这里我有一个简单的CRTP案例: #包括 #包括 模板 班级基础 { constexpr 静态 size_t impl_num = Impl::num; }; 模板 这里我有一个简单的CRTP案例: #include <cstddef> #include <utility> template <typename Impl> class base { constexpr static size_t impl_num = Impl::num; }; template <typename Impl> class deriv : public base<deriv<Impl>> { friend class base<deriv<Impl>>; constexpr static size_t num = Impl::num_in; }; class actual_impl { public: constexpr static size_t num_in = 10; }; using my_type = deriv<actual_impl>; int main() { my_type a{}; } 这个片段编译得很好,但是当我将基类更改为: #include <cstddef> #include <utility> template <typename Impl> class base { constexpr static std::make_index_sequence<Impl::num> idx{}; }; template <typename Impl> class deriv : public base<deriv<Impl>> { friend class base<deriv<Impl>>; constexpr static size_t num = Impl::num_in; }; class actual_impl { public: constexpr static size_t num_in = 10; }; using my_type = deriv<actual_impl>; int main() { my_type a{}; } Clang 抱怨error: no member named 'num' in 'deriv<actual_impl>'。我只是很困惑为什么第一种情况有效但第二种情况不起作用,这两种情况之间的根本区别是什么,因为在我看来,在这两种情况下 Impl::num_in 都在基类中使用。 一般来说,基类是否可以使用 Impl 中的 typedef 或 constexpr? 根本的区别是当您尝试访问 Impl 类的内部时。 Impl中的base<Impl>是一个不完整的类型,并且你可以用它做什么有一定的限制。 特别是,您无法访问 num 内的 base 数据成员,这就是该行的原因 constexpr static std::make_index_sequence<Impl::num> idx{}; 导致编译错误。请注意,要定义 base 类,编译器必须知道当时 Impl::num 的值。 与此相反,在第一个示例中,Impl::num仅用于初始化impl_num的值,否则不依赖于Impl::num。该初始化的实例化稍后发生,当 Impl 成为完整类型时。因此,没有错误。 如果稍微改变一下定义, template<typename Impl> class base { constexpr static decltype(Impl::num) impl_num = Impl::num; // or constexpr static auto impl_num = Impl::num; } 并使 impl_num type 依赖于 Impl,你会因为同样的原因得到同样的错误。 添加间接没有帮助,以下代码也无法编译: template<typename Impl> class base { constexpr static size_t impl_num = Impl::num; constexpr static std::make_index_sequence<impl_num> idx{}; }; 一般来说,基类是否可以使用 Impl 中的 typedef 或 constexpr? 这要看情况。您只能在 Impl 是完整类型时发生实例化的上下文中使用它们。例如, template<typename Impl> class base { public: void foo() { decltype(Impl::num) impl_num = 0; } }; 很好,但是 template<typename Impl> class base { public: decltype(Impl::num) foo() { return 0; } }; 不是。 避免 CRTP 中不完整类型潜在问题的标准技巧是引入辅助特征类: // Just forward declarations template<typename Impl> class deriv; class actual_impl; using my_type = deriv<actual_impl>; template<class> struct traits; template<> struct traits<my_type> { using num_type = std::size_t; }; template <typename Impl> class base { public: typename traits<Impl>::num_type foo() { return 0; } }; // Now actual definitions // ... 在这里,要访问 traits<Impl> 内部结构,Impl 不必是完整类型。
C++11:在类中查找方法和错误:嵌套名称说明符中使用的类型不完整
使用 C++11 中的 CRTP 习惯用法,我试图检查派生类是否具有名为 size 的方法。 #包括 模板 结构 IsContainer { 模板<
我有一个 CRTP 层次结构,其中子级定义了父级使用的类型,但该类型具有对父级的回调: 模板类回调> 类别选项1 {...
正如 Evg 的 crtp-pass-types-from-driven-class-to-base-class 中所述,编译器无法推导出 Base 类声明中的类型 Impl::TType: 模板 结构...
我正在学习CRTP C++模式 我的代码 模板 类基序{ 民众: void sendOrder() {static_cast(this)->send();} 无效发送(){cout<< "S...
我正在学习CRTP C++模式 我的代码 模板 类基序{ 民众: void sendOrder() {static_cast(this)->send();} 无效发送(){cout<< "S...
我正在学习CRTP C++模式 我的代码 模板 类基序{ 民众: void sendOrder() {static_cast(this)->send();} 无效发送(){cout<< "S...
如何让 MSVC 在 c++20 编译时查看静态 constexpr 成员变量和函数?
背景 我试图在编译时在 CRTP 类中访问 constexpr 变量。下面是一个 MVCE。 模板 结构体CRTP { 静态 constexpr int get_va...
假设我有一个模板类,如下所示: 模板 我的班级 { 民众: MyClass(std::string const& 名称){ s = 姓名; } T return_var1() {...
我有一个模板类,我想专门针对许多不同的类型。就像是: #包括 #包括 #包括 // 允许静态为...
我正在开发基于模型的系统工程(MBSE)的框架。在此,我有一个名为 Bridge 的构造。桥接器可以从一个电子设备发送信号(异步调用)和/或操作(同步调用)...