2017-08-28 96 views
2

在下面的C++ 14代碼中,我想使用可變參數模板創建一個PossibleTypes容器。接下來,我想用先前指定類型的成員元組創建另一個容器。重複使用可變參數類型

這樣做會怎麼樣?我想讓Foo包含一個元組< int,double>,就像主題的模板化類型一樣。

非常感謝提前。

#include <iostream> 
#include <tuple> 
#include <type_traits> 

template <typename... T> 
struct PossibleTypes {}; 

PossibleTypes<int,double> topics; 

template <typename... T> 
struct Foo{ 
    std::tuple<T...> member; 
}; 

int main(){ 
    Foo<??(topics)??> x; 
    return 0; 
} 

回答

10

有多種方法可以做到這一點。你不需要全部瞭解它們,只需找到一個具有你想要的功能。

以下是三種完全不同的方法。

擷取音訊從實例爲模板

template<class Src, template<class...>class Dest> 
struct transcribe; 
template<class Src, template<class...>class Dest> 
using transcribe_t=typename transcribe<Src,Dest>::type; 

template<template<class...>class Src, class...Ts, template<class...>class Dest> 
struct transcribe<Src<Ts...>, Dest>{ 
    using type=Dest<Ts...>; 
}; 

然後:

transcribe_t<decltype(topics), Foo> x; 

侵入通過修改富

這也可以侵入通過修改Foo取束,而不是進行一個揹包。

template <class Bundle> 
struct Foo; 

template <typename... T> 
struct Foo<PossibleTypes<T...>>{ 
    std::tuple<T...> member; 
}; 

template <template<class...>class Z, typename... T> 
struct Foo<Z<T...>>{ 
    std::tuple<T...> member; 
}; 

則:

Foo<decltype(topics)> x; 

它可以是更實際的,如果你不只是在傳遞一組...參數。

價值爲基礎的元編程

我們也可以處理這個使用基於價值的元編程:

template<class T> 
struct tag_t {constexpr tag_t(){} using type=T;}; 
template<class T> 
constexpr tag_t<T> tag{}; 
template<template<class...>class Z> 
struct ztemplate_t { 
    constexpr ztemplate_t() {} 
    template<class...Ts> using apply=Z<Ts...>; 
    template<class...Ts> 
    constexpr tag_t<Z<Ts...>> operator()(tag_t<Ts>...)const{ return {}; } 
}; 
template<template<class...>class Z> 
constexpr ztemplate_t<Z> ztemplate{}; 

template<class Tag> 
using type=typename Tag::type; 

template <class... T> 
struct PossibleTypes { 
    template<template<class...>class Z> 
    constexpr auto operator()(ztemplate_t<Z> z) const { 
    return z(tag<T>...); 
    } 
}; 

給我們:

int main(){ 
    type<decltype(topics(ztemplate<Foo>)) > x; 
    return 0; 
} 

這是非常漂亮的。 Live example

tag將類型提升爲值。 ztemplate將模板提升爲一個值。

ztemplate<some_template>(tag<T0>, tag<T1>)返回施加some_templateT0, T1tag_t<some_template<T0, T1>>的結果的tag

要回到標籤的類型,我們做一個type<decltype(some_tag_expression)>

我修改了您的PossibleTypes也有一個operator()(ztemplate)將模板應用於存儲在PossibleTypes中的類型。

隨着您進行更多基於類型的操作,這種瘋狂效果會更好,因爲C++中的基於值的編程比模板語法更具表現力且更易於使用。

+0

@mihai以上都不需要實例化對象?在任何情況下,我都會創建該類型。然後,因爲你的代碼做了,我創建了一個類型的實例(證明它工作,我猜)。刪除然後'X',你有一個類型表達式,沒有實例。使用typedef或使用給它一個名字,或其他。 – Yakk

+0

阿爾夫對不起。代碼的另一部分存在問題。很棒! –