2

我遇到以下問題。我有一些類將輸入數組映射到輸出數組。我想有float類型,以及陣列作爲模板參數的長度,所以映射類是這樣的:類型,積分常量和模板模板參數的變量模板

template <typename FloatType, std::size_t input, std::size_t output> 
class Mapper 
{}; 

template <typename FloatType, std::size_t input, std::size_t output> 
class FirstMapper : public Mapper<FloatType, input, output> 
{}; 

template <typename FloatType, std::size_t input, std::size_t output> 
class SecondMapper : public Mapper<FloatType, input, output> 
{}; 

到目前爲止好。我的目標是編寫一個堆疊這些Mapper類的不同實例的類。我希望能寫出這樣的代碼:

StackedMapper< 
       double,  // the FloatType, obviously 
       input_1,  // the size of the first mapper's input array 
       FirstMapper, // the template template type of the first mapper 
       input_2,  // the size of the first mapper's output and 
          // second mapper's input array 
       SecondMapper, // the template template type of the second mapper 
       input_3,  // the size of the second mapper's output and 
          // third mapper's input array 
       FirstMapper, // the template template type of the third mapper 
       output  // the size of the third mapper's output array 
       // ... any additional number of Mapper classes plus output sizes 
      > stacked_mapper; 

內部,StackedMapper類應該映射器實例存儲在std::tuple。我期望元組有以下類型:

std::tuple< 
      FirstMapper<double, input_1, input_2>, 
      SecondMapper<double, input_2, input_3>, 
      FirstMapper<double, input_3, output> 
      // ... 
      >; 

如省略號所示,我想添加任意數量的Mapper類。正如您從註釋中看到的那樣,一個圖層的輸出大小等於下一個圖層的輸入大小。對於堆棧中的所有映射器,浮點類型只能定義一次。

有沒有人有想法?我見過this問題,它解決了交替類型(積分常量和類型)問題,但它似乎不適用於模板模板參數,因爲我總是遇到類似expected a type, got 'FirstMapper'的錯誤。

有沒有人有這個想法?

+3

如果您對所有內容使用類型,而不是模板模板參數和非類型模板參數,則更方便。閱讀@ Yakk元編程答案中的一個例子,例如http://stackoverflow.com/a/32056973/ – dyp

+0

@dyp:感謝發佈該鏈接,這是一個好的 –

回答

2

下面是簡要介紹了模板元編程基於Boost.MPL。其實質是爲所有事情使用類,以便儘可能多地獲得代碼中的規律性。

首先,使用integral_constant來包裝常量。這被稱爲「元數據」,並且該值被包含爲嵌套數據成員value

// nullary metafunction ("metadata"), wrap "value" 
template<class T, T v> 
struct integral_constant 
{ 
    using type = integral_constant<T, v>; 
    using value_type = T; 
    static constexpr auto value = v; 
}; 

您可以使用類,包括整型常量的元數據,作爲參數傳遞給「元函數」:返回自己的價值作爲一個叫做type嵌套型普通類模板。

// regular metafunction: class template that takes metadata "X", returns "type" with "value" squared 
template<class X> 
struct square 
: 
    integral_constant<typename X::value_type, (X::value * X::value)> 
{}; 

爲了避免模板,模板參數圍繞元功能路過的時候,可以使用元函數類:一類是包含嵌套元函數普通班apply

// higher-order metafunction: class that has nested metafunction "apply" which returns square 
struct square_f 
{ 
    template<class X> 
    struct apply 
    : 
     square<X> 
    {}; 
}; 

要看到上面定義的有用性,通過在integral_constant<int, 2>上應用square_f元函數類兩次來計算整數2的平方和四次方是非常簡單的,其中integral_constant<int, 2>

// regular metafunction that takes higher-order metafunction "F" and metafunction "X" and returns "F<F<X>>" 
template<class F, class X> 
struct apply_twice 
: 
    F::template apply<typename F::template apply<X>::type> 
{}; 

template<class X> 
struct quartic 
: 
    apply_twice<square_f, X> 
{}; 

int main() 
{ 
    using two = integral_constant<int, 2>; 
    static_assert(4 == square<two>::value, "");   
    static_assert(16 == quartic<two>::value, ""); 
} 

Live Example

它推廣爲可變參數模板參數,只需要使用

template<class... Xs> 
struct some_fun; 

於拍攝參數的可變參數數量元函數。這留作練習。主要觀點是通過合適的包裝將每個(數據,類,函數)參數統一視爲一個類。

注意:我使用繼承來自動嵌入派生類中嵌套type。這種技術被稱爲「元功能轉發」,並減少了雜亂的數量。

+0

謝謝,看起來真不錯。我會嘗試的。 –

+0

我部分地嘗試了成功的解決方案。但後來我得到了更改請求,以支持在運行時更改輸入/輸出大小。因此,我不得不重構現在不再使用模板的代碼。 –

相關問題