2016-11-09 12 views
2

メタプログラミングの目的のために、私はメンバ関数ポインタを型に格納し、後でそれを使ってテンプレートをパラメータ化したいと思います。類推によりメンバ関数ポインタをテンプレートパラメータとして使用するために格納/取得する方法は?

は、ここで私はinteger_constant型ではint型を格納する方法の実施例である:

template< int I > 
struct integer_constant { 
    static constexpr int value = I; 
}; 

template <int I> 
struct A { 
    // (client type, probably does other things with I) 
    static constexpr int value = I; 
}; 

namespace { 
    using cStored= integer_constant<42>; // store value 
    static_assert(cStored::value == 42, ""); 

    // ... 

    using aUseStored = A<cStored::value>; // use value as template parameter 
    static_assert(aUseStored::value == 42, ""); 
} 

私はメンバ関数ポインタと同じことを行うことができますか?そうでない場合は、どうしてですか?

template <typename MT> 
struct B { 
    static constexpr s_member_fn_type value = MT::value; 
}; 

namespace { 
    using bUseStored = B<cStored>; 
} 

しかし、私のクライアントクラスならば、これは助けないA

struct S{ 
    void foo() {} 
}; 

typedef void (S::*s_member_fn_type)(); 

template< s_member_fn_type M > 
struct member_fn_constant { 
    static constexpr s_member_fn_type value = M; 
}; 

template <s_member_fn_type M> 
struct A { 
    // (client type, probably does other things with M) 
    static constexpr s_member_fn_type value = M; 
}; 

namespace { 
    using cStored = member_fn_constant<&S::foo>; // store value 

    // clang is ok with the following line 
    // gcc 6.2: error: non-constant condition for static assertion 
    // gcc 6.2: error: '(s_member_fn_type)member_fn_constant<&S::foo>::value' is not a constant expression 
    static_assert(cStored::value == &S::foo, ""); 

    // following line gives: 
    // clang 3.9.0 error: non-type template argument is not a pointer to member constant 
    // gcc 6.2: error: could not convert template argument 'member_fn_constant<&S::foo>::value' to 'void (S::*)()' 
    using aUseStored = A<cStored::value>; // use value as template parameter 
    //static_assert(aUseStored ::value == &S::foo, ""); 
} 

私は次のように私は、代わりに、関数ポインタの、ラッパー構造体を渡すことによって、間接の余分なレベルを追加できることを理解しますメンバー関数ポインタを取るように既に定義されています。

答えて

3

Pre-C++ 17、メンバー関数へのポインタは定数式ではありません。

C++ 17より、これは、N4268で指定された定数式です。あなたはそれをg ++ 6からそれを支えたと主張したが、それは真実ではないようですしてい++ C++ Support in Clang

グラムを見ることができるよう

打ち鳴らすが打ち鳴らす3.5から-std=c++1zとそれを支えてきた、C++ Standards Support in GCC

+0

感謝を参照してください。はい、 '-std = C++ 1z'でclangで動作するようです –

関連する問題