c++ - 如何将模板化类实例作为模板参数传递给另一个模板?

标签 c++ templates microcontroller avr

我有一个类模板,我想将它的实例作为模板参数传递给另一个类模板。如:

typedef Pin<(uint16_t)&PORTB,0> B0;
typedef Pin<(uint16_t)&PORTB,1> B1;

然后我想像这样传递它们:

Indicator<B0,B1> Ind1;

我正在使用的 pin 类模板:

template <uint16_t tPort, uint8_t tBit>
class Pin
{
public:
    static constexpr uint16_t Port = tPort;
    static constexpr uint16_t DDR = tPort-1;
    static constexpr uint16_t PIn = tPort-2;
    static constexpr uint8_t Bit = tBit;

    static constexpr void  Toggle() 
    {
        *reinterpret_cast<uint16_t*>(Port) ^= (1<<Bit);
    }

    static constexpr void PullHigh() 
    {
        *reinterpret_cast<uint16_t*>(Port) |= (1<<Bit);
    }

    static constexpr void PullLow() 
    {
        *reinterpret_cast<uint16_t*>(Port) &= ~(1<<Bit);
    }

    static constexpr void SetOutput() 
    {
        *reinterpret_cast<uint16_t*>(DDR) &= ~(1<<Bit);
    }

    static constexpr void SetInput() 
    {
        *reinterpret_cast<uint16_t*>(DDR) |= (1<<Bit);
    }

    static constexpr void SetHighImpedance() 
    {
        *reinterpret_cast<uint16_t*>(Port) &= ~(1<<Bit);
        *reinterpret_cast<uint16_t*>(DDR) &= ~(1<<Bit);
    }

    static constexpr bool Read() 
    {
        return (*reinterpret_cast<uint16_t*>(PIn) & (1<<Bit));
    }
};

我已经能够将它们传递给模板函数。我假设模板模板参数可能是答案。但是一直无法让它工作......

最佳答案

非类型模板参数不限于整数。您似乎传递了一个 uint16_t 只是为了将它重新解释为一个指针。相反,您可以将指针本身作为模板参数传递。

另请注意,constexpr 上下文中不允许使用 reinterpret_cast

在编译时传递指针看起来像这样:

template <uint16_t* tPort, uint8_t tBit>
class Pin
{
    // ...
};

它会像这样使用:

using B1 = Pin<&PORTB, 1>;

假设您要编写 Indicator 模板类,它看起来像这样:

template<typename P1, typename P2>
struct Indicator {
    // ...
};

如果您担心强制 P1P2 成为引脚,可以通过创建类型特征并对其断言来完成:

// Base case
template<typename>
struct is_pin : std::false_type {};

// Case where the first parameter is a pin
template <uint16_t* tPort, uint8_t tBit>
struct is_pin<Pin<tPort, tBit>> : std::true_type {};

然后,使用你的断言:

template<typename P1, typename P2>
struct Indicator {
    static_assert(is_pin<P1>::value && is_pin<P2>::value, "P1 and P2 must be pins");

    // ...
};

然后,要制作一个接收 Indicator 的函数,您可以执行以下操作:

// Pass type only, and use static members
template<typename IndicatorType>
void do_stuff() {
    IndicatorType::stuff();
}

// Pass an instance of the class
template<typename IndicatorType>
void do_stuff(IndicatorType indicator) {
    indicator.stuff();
}

这些函数是这样调用的:

// Passing only the type
do_stuff<Indicator<B1, A1>>();

// Passing an instance
Indicator<B1, A1> indicator;

do_stuff(indicator);

这次我不会担心 IndicatorType 不是指标。任何充当指标的类都将被接受,如果不能像指标一样使用,则会发生编译时错误。这将使指标的实现方式更加灵活。

此外,我建议您阅读更多或更深入的有关 C++ 模板的教程。有时会被忽视,它是 C++ 最重要和最复杂的特性之一。

关于c++ - 如何将模板化类实例作为模板参数传递给另一个模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45559355/

相关文章:

c++ - 无法推断重载函数的模板参数

c++ - 将未签名的char Buffer拆分并存储到结构中

microcontroller - 通过JTAG恢复STM32 MCU磨掉的标记

c++ - consteval 函数是否允许依赖于函数参数的模板参数?

c++ - c++模板规范和重载的解析

c++ - 替换 SHDOLCC.DLL 文件以自定义 Web 浏览器的上下文菜单

c++ - 类模板 cpp、hpp、cpp

c++ - 类型组的模板类的成员特化?

azure - 模板参数 JToken 类型在 Azure 中无效(预期 'String, Uri' 。实际 'Integer' )

c - Tiva 上的 I2C 接口(interface)