gpt4 book ai didi

c++ - 使用条件模板 c++ 调用函数

转载 作者:行者123 更新时间:2023-11-28 05:15:24 24 4
gpt4 key购买 nike

我正在编写一个嵌入式设备驱动程序库 (Arduino Mega),其中代码大小和性能密切相关。

SPI Controller 有一个操作序列:

  1. 选择SPI从节点
  2. 传输数据
  3. 取消选择从节点

选择/取消选择是事务的开始/停止。这是通过将引脚置为高电平或低电平来完成的。 SPI 从节点电路可以使用标准的非反相数字信号(选择 == 高压,取消选择 == 接地)或反相信号(选择 == 接地,取消选择 == 高压)。

select() 可以使用运行时条件来实现,以检查引脚是否反转(然后发出 clearPin())或不反转(发出 setPin())。取消选择()也是如此。使用常量和静态定义,编译器应该能够在编译时解决条件。事实证明,编译器 (Avr-gcc 4.9) 并不总是意识到可以减少(和内联)这些表达式。

因此,为了解决这个问题,我尝试使用如下条件模板:

enum class SelectPinType : const bool
{
STANDARD = false,
INVERTED = true
};

template <SelectPinType tInvertedSelect>
struct SelectPin;

template<>
struct SelectPin<SelectPinType::INVERTED>
{
const Pin::IOPin &mChipSelectPin;

inline void select() const __attribute__((always_inline))
{
Pin::clr(mChipSelectPin); // Select inverted pin
}
inline void deselect() const __attribute__((always_inline))
{
Pin::set(mChipSelectPin); // Deselect inverted pin
}
};

template<>
struct SelectPin<SelectPinType::STANDARD>
{
const Pin::IOPin &mChipSelectPin;

inline void select() const __attribute__((always_inline))
{
Pin::set(mChipSelectPin); // Select standard pin
}
inline void deselect() const __attribute__((always_inline))
{
Pin::clr(mChipSelectPin); // Deselect standard pin
}
};

然后可以像这样使用 select() 和 deselect() :

// Uses digital pin # 33 as Select pin
static struct SelectPin<SelectPinType::INVERTED> SpiSel
{
Pin::PIN_DIO_33
};
...
SpiSel.select();
doTransfer(dataBuffer);
SpiSel.deselect();

一切正常,select()/deselect() 编译为少于 5 条汇编指令。但是,我无法找到如何传递结构 SelectPin 的实例而无需在函数参数列表中指定模板条件的解决方案。换句话说,如果我想在函数中包装 Select-Transfer-Deselect,我必须执行以下操作:

// Inverted select pin transaction
inline void doTransaction(const SelectPin<SelectPinType::INVERTED> &fSelectPin, Spi::Transfer &fTransfer)
{

// Perform the SPI transaction
fSelectPin.select();
doTransfer(fTransfer);
fSelectPin.deselect();

// Done
return;
}

// Non-inverted select pin transaction
inline void doTransaction(const SelectPin<SelectPinType::STANDARD> &fSelectPin, Spi::Transfer &fTransfer)
{

// Perform the SPI transaction
fSelectPin.select();
doTransfer(fTransfer);
fSelectPin.deselect();

// Done
return;
}

因为我可以在不使用模板的情况下为倒置和非倒置选择引脚编写重载函数,所以我基本上回到了原点。

有没有办法解决这个问题,以便我实质上可以将基本模板用作单个函数定义中的参数?类似的东西:

// Accept any condition for the SelectPin template
inline void doTransaction(const SelectPin<SelectPinType::*> &fSelectPin, Spi::Transfer &fTransfer)
{

// Perform the SPI transaction
fSelectPin.select();
doTransfer(fTransfer);
fSelectPin.deselect();

// Done
return;
}

注意是的,我意识到 2 个重载函数可以立即完成这项工作,但我觉得除了我糟糕的选择引脚之外,这可能具有一般意义。

最佳答案

你想要的语法是:

template <SelectPinType E>
void doTransaction(const SelectPin<E> &fSelectPin, Spi::Transfer &fTransfer)
{
// Perform the SPI transaction
fSelectPin.select();
doTransfer(fTransfer);
fSelectPin.deselect();
}

或更短,但约束更少:

template <typename T>
void doTransaction(const T& fSelectPin, Spi::Transfer &fTransfer)
{
// Perform the SPI transaction
fSelectPin.select();
doTransfer(fTransfer);
fSelectPin.deselect();
}

关于c++ - 使用条件模板 c++ 调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42751060/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com