簡體   English   中英

類型、整型常量和模板模板參數的可變模板

[英]Variadic templates of types, integral constants and template template parameters

我有以下問題。 我有一些類執行輸入數組到輸出數組的映射。 我想要 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 類。 正如您從評論中看到的那樣,一層的輸出大小等於下一層的輸入大小。 浮點類型將只為堆棧中的所有映射器定義一次。

有人有想法嗎? 我見過這個問題,它解決了交替類型(整型常量和類型)問題,但是它似乎不適用於模板模板參數,因為我總是收到類似expected a type, got 'FirstMapper'的錯誤expected a type, got 'FirstMapper'

有沒有人對此有想法?

下面簡單介紹一下基於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>
    {};
};

要查看上述定義的square_f ,通過在square_f integral_constant<int, 2>上兩次應用square_f元函數類來計算整數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, "");
}

現場示例

要將其推廣到可變參數模板參數,只需使用

template<class... Xs>
struct some_fun;

對於采用可變數量參數的元函數。 這留作練習。 重點是通過合適的包裝器將每個(數據、類、函數)參數統一視為一個類。

注意:我使用繼承將嵌套type自動嵌入到派生類中。 這種技術被稱為“元函數轉發”,並減少了typename F<T>::type混亂的數量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM