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

时间:2017-03-12 17:58:16

标签: c++ templates conditional

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

SPI控制器有一系列操作:

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

    select()可以使用运行时条件来实现,以检查引脚是否被反转(然后发出clearPin())或者不发出(发出setPin())。 deselect()也是如此。使用consts和static定义,编译器应该能够在编译时解决条件。事实证明,编译器(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个汇编指令。但是,我无法找到如何传递struct 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个重载函数会立即完成这项工作但我觉得除了我的crapy选择引脚之外,这可能会产生一般性影响。

1 个答案:

答案 0 :(得分:1)

您想要的语法是:

(df.groupby('id')
 .apply(lambda g: pd.Series({'max': g.value[g.min_max == "max_val"].max(), 
                             'min': g.value[g.min_max == "min_val"].min()})))

#    max    min
#id     
# 1    3     10
# 2   20    -10

甚至更短,但约束更少:

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