2017-08-08 599 views
1

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

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

后来我想通过他们,如:

Indicator<B0,B1> Ind1; 

引脚类模板,我使用:

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)); 
    } 
}; 

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

回答

1

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

此外,请注意reinterpret_cast不允许在constexpr上下文中。

在编译时传递的指针是这样的:

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++最重要和最复杂的特性之一。

相关问题