2017-08-08 604 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++最重要和最複雜的特性之一。

相關問題