2017-01-18 4 views
3

std::integral_constantの「コンテナバージョン」を作成したいと思います。std :: integral_constantのようなコンテナを作成する

enum class A { 
    a = 1 << 0, 
    b = 1 << 1, 
    c = 1 << 2 
}; 

template<typename T, T... Values> 
struct static_container final {}; 

template<typename T, T... Ts> 
constexpr auto make_static_container(T...) { // wrong 
    return static_container<T, Ts...>{}; 
} 

template<typename F, F... FF> 
void inline set(static_container<F, FF...>) { 
    std::cout << sizeof... (FF) << std::endl; 
} 

int main() { 
    constexpr static_container<A, A::a, A::b> sc1{}; //ok 
    constexpr auto sc2 = make_static_container(A::a, A::c); // not-ok 

    set(sc1);  
    set(sc2);  
} 

あなたは私が明示的なタイプでsc1を作成することができることを見ることができます上:それは要素型と非型パラメータでパラメータ化タイプです。

今、(冗長な)列挙型を指定せずにこのような型を作成するヘルパ関数が必要です。ここ

出力は次のようになります。

2 
0 

任意のヒント?

+1

取得しているエラーとは何ですか? – DeiDei

+1

VS2015でコンパイル – wally

+2

[clangでコンパイル](http://coliru.stacked-crooked.com/a/604bd7401ede4373) – wally

答えて

3

ではありませんt0/tsので、これはC++ 11/C++ 14で(私の知る限り知っている)ことは不可能です関数は今ではなくTのdirectlよりstd::integral_constant<T>秒を取っているので、

template<typename T, T... Values> 
constexpr auto make_static_container(std::integral_constant<T, Values>...) noexcept { 
    return static_container<T, Values...>{}; 
} 

呼び出し場所を変更する必要があります:std::integral_constantについては、ここでそれは次のようになりますy;それは少し騒々しいですが、変数のテンプレートがすぎ苦痛であることから、それを維持:(。デモbecomes unnecessary in C++17static_container::valueの脇に、別の定義として)

template<A a> 
using A_ = std::integral_constant<A, a>; 

template<A a> 
constexpr A_<a> a_{}; 

int main() { 
    // explicit construction via alias template: 
    constexpr auto sc1 = make_static_container(A_<A::a>{}, A_<A::b>{}); 
    // implicit construction via variable template: 
    constexpr auto sc2 = make_static_container(a_<A::a>, a_<A::c>); 

    set(sc1); 
    set(sc2); 
} 

Online Demo

+0

テンプレート変数を使った面白い考え。 – wimalopaan

+0

@wimalopaan:最近まで私は彼らの意見や使用はありませんでしたが、最近[Boost.Hana](http://www.boost.org/libs/hana/)を使って私に新しい視点を与えました。 : - ] – ildjarn

3

あなたの問題は、あなたが

template<typename T, T... Ts> 
constexpr auto make_static_container(T... /* !!! unused values !!! */) { // wrong 
    return static_container<T, Ts...>{}; 
} 

だからのみ推定されるテンプレートはTで返された値を作成するためのテンプレート引数のリストに関数の引数を渡さないということです。テンプレート非型の値Tsは導かれません。返されるタイプは、0の値を持つ

return static_container<T>{}; 

です。

あなたは関数の引数を使用して、それらをparamersをタイプしないテンプレートとして渡すことができます。

template<typename T0, typename ... Ts> 
constexpr auto make_static_container (T0 const t0, Ts const ... ts) 
{ return static_container<T0, t0, ts...>{}; } 

のようなものが、値があなたのコメントへのフォローアップとしてconstexpr

+0

はい、実際には不可能です。なぜなら、constexpr関数は、非constexprコンテキストでも呼び出し可能でなければならないからです。 – wimalopaan

+0

パラメータリストではなくmake_static_containerの明示的なインスタンス化とともに、make_static_containerのテンプレートテンプレートパラメータとしてstd :: integral_constant <>を使用する解決策があるのだろうかと思います....しかし、私はそれを正しく行うことはできません。 – wimalopaan

関連する問題