2017-10-10 91 views
3

考慮一下:指定默認模板

template <typename Pack, template <typename...> class = std::tuple> struct foo; 

template <template <typename...> class P, typename... Ts, template <typename...> class Q> 
struct foo<P<Ts...>, Q> { 
    using type = Q<P<Ts>...>; 
}; 

我已經放在默認模板中的typedef是std::tuple,使這個編譯,但我真正想要的是P默認模板,和我不知道任何允許這個的語法。我一直typedef的簡單說明這一點,這是試圖讓P爲默認模板。所以我想出了以下解決方法,看起來有點醜:

template <typename Pack, template <typename...> class...> struct foo; 

template <template <typename...> class P, typename... Ts, template <typename...> class Q> 
struct foo<P<Ts...>, Q> { 
    using type = Q<P<Ts>...>; 
}; 

template <template <typename...> class P, typename... Ts> 
struct foo<P<Ts...>> { 
    using type = P<P<Ts>...>; 
}; 

有沒有比這更好的方法呢?也許一些我不知道的C++ 17語法?

+0

你想要什麼來實現呢?某些給定的'foo <...> :: type'表達式的預期結果是什麼? – sehe

+0

@ sehe要包分成特定小包裝(如上面的例子,但更復雜的),但我需要包含所有的小包裝,也就是默認模板的作用。 – prestokeys

+0

如何。特別。如果你說'foo :: type'應該是什麼結果?如果這不是正確的用法,那是什麼?那會是什麼結果(假設你神奇地有一個工作實現) – sehe

回答

2

在這種情況下,using(與template相結合)是你的朋友。

你需要一個類型的特徵提取容器Pack,舉例

template <typename> 
struct bar; 

template <template <typename...> class P, typename ... Ts> 
struct bar<P<Ts...>> 
{ 
    template <typename ... Us> 
    using templ_type = P<Us...>; 
}; 

這樣你就可以提取默認值,第二個模板參數,從Pack如下

template <typename Pack, 
      template <typename...> class = bar<Pack>::template templ_type> 
struct foo; 

以下是完整的編譯示例

#include <type_traits> 

template <typename ...> 
struct baz 
{ }; 

template <typename> 
struct bar; 

template <template <typename...> class P, typename ... Ts> 
struct bar<P<Ts...>> 
{ 
    template <typename ... Us> 
    using templ_type = P<Us...>; 
}; 

template <typename Pack, 
      template <typename...> class = bar<Pack>::template templ_type> 
struct foo; 

template <template <typename...> class P, typename... Ts, 
      template <typename...> class Q> 
struct foo<P<Ts...>, Q> 
{ using type = Q<P<Ts>...>; }; 

int main() 
{ 
    foo<baz<short, int, long>> f0; 

    static_assert(std::is_same<decltype(f0)::type, 
     baz<baz<short>, baz<int>, baz<long>>>{}, "!"); 
} 
1

如果你正在尋找一個不同的默認這是一個身份,你可以創建這樣的事情:

template <class... I> struct foo_id_impl; 
template <template <class...> class P, class... Ts> 
struct foo_id_impl<P<Ts>...> { using type = P<P<Ts>...>; }; 

template <class... Id> 
using foo_id = typename foo_id_impl<Id...>::type; 

template <class Pack, template <class...> class = foo_id> 
struct foo; 

我不知道那是一定比你的更好的解決方案,但也許如果需要這個在多個地方。