C++从编译时多态性中隐藏模板习语

标签 c++ templates polymorphic-associations c++03

我正在编写一个 C++ 硬件抽象层 (HAL),它需要尽可能快。

多态性提供了最好的 API,但虚拟表查找确实会降低代码的速度。

这引导我结合使用模板和策略来获得编译时多态性。但是因为具有不同参数的模板被实例化为完全不同的类型,所以我不能在函数调用中互换使用它们,除非函数也是模板。

但是,我不想强​​迫我的 HAL 库的用户将所有函数编写为模板,因为我已经使用了模板。

为了便于说明,假设这是我的 HAL:

template<typename T_POLICY>
class I2CManager {
public:     
    void send(uint8_t data) {
        T_POLICY::send(data);
        ++sent_data; 
    }
private:
    int sent_data; // Just to illustrate that I2CManager has state
};

class I2C1 {
    static void send(uint8_t data) { /* Run some code here */ }
};

class I2C2 {
    static void send(uint8_t data) { /* Run other code here */ }
};


// OTHER HW
template<typename T_POLICY>
class UARTManager { ··· };

class UART1 { ··· };
class UART2 { ··· };

template<typename T_POLICY>
class TIMERManager { ··· };

class TIMER1A { ··· };
class TIMER1B { ··· };

这行得通,我现在可以创建一个具有不同策略的 I2CManager,如下所示。我什至可以让多个 I2CManager 同时以不同的策略运行。

I2CManager<I2C1> i2c1;
I2CManager<I2C2> i2c2;

i2c1.send(0x11); // This works
i2c2.send(0x11); // This also works

现在,i2c1i2c2 具有相同的公共(public)方法,但它们不可互换。因此,我的 HAL 库的用户也被迫使用模板。

// THIS DOES NOT WORK
void foo(I2CManager m) { m.send(0x11); }
foo(my_manager_1);

// BUT THIS WORKS
template<typename T>
void foo(I2CManager<T> m) { m.send(0x11); }
foo(i2c1);

我能否以某种方式获得编译时多态性但允许最终用户将其视为正常多态性?为了速度,我不在乎我的库中的内部代码是否变得丑陋或难以阅读,但 API 必须尽可能简单和直观。

实际上,我希望 foo() 专门针对不同的参数(并在代码中复制),就好像它是一个模板一样,但我不想让我的库的用户注意到它是一个模板函数。也欢迎替代模板。

我不知道这是否可能,但我已经阅读了一些关于概念的内容,它们将出现在下一个 C++ 标准中。我想要编译时多态性,但与运行时多态性一样用户友好。


注意事项:

  • 因为我正在连接 HW,所以我的 HWManagers 的每个实例化 不同的策略将是唯一的(即只有一个 HWManager 实例和一个 HWManager 实例, 可能同时存在也可能不同时存在)。

  • 所有实例都由库创建为全局变量,并且 不可堆放。

  • 所有的策略方法都非常短,所以有多个唯一的 由于模板的实例比虚拟表更可取 为了执行速度。

  • 代码大小并不重要(对于嵌入式系统而言),但 RAM 使用量 和执行速度。我需要尽可能多的解决 在编译期间。再一次,我愿意有一个过度臃肿 可执行以避免运行时解析。

  • 仅支持 C++03


已编辑代码示例

最佳答案

All instances are created by the library as global variables, and are not heapable.

你的意思是这样的,对吧?

static HWManager<DrierPolicy> drierManager;

static HWManager<FridgePolicy> fridgeManager;

那么,让用户知道它们并允许她/他直接使用它们有什么错:

drierManager.doStuff();

fridgeManager.doStuff();

然后……

Because I'm interfacing HW, each instantiation of my HWManagers with different policies will be unique

那为什么要将 doStuff 方法实现为实例方法呢?一些静态方法还不够好吗?

(这些是问题,而不是批评。是的,我知道,这不是一个答案 - 虽然它可能是一个 - 但我需要评论没有提供的额外格式)

关于C++从编译时多态性中隐藏模板习语,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39570617/

相关文章:

c++ - func return list<int> with args (int arry[int], int array[int])

c++ - 模拟具体类 : templates and avoiding conditional compilation

c++ - 在 C++ 中使用鸭子类型(duck typing)的模板

ruby-on-rails - 为什么在多态关联中不能有外键?

c++ - C/C++ 构建步骤

c++ - 为什么某些 IDE 不缩进 switch 中的 case 语句?

sql - jpa 对子类的连接查询

ruby-on-rails - Rails 4:无法更新多态对象

c++ - 从一组文件中读取

c++ - 为模板参数的所有组合实例化函数,在运行时选择实例化