5

他の私の質問に基づいています。

次のコードを検討してください

template<typename T, int N>
struct A {
  typedef T value_type; // save T to value_type
  static const int size = N; // save N to size
};

テンプレート パラメータとしてvalue_typeandを使用できます。size

typedef A<int, 2> A1;
typedef A<A1::value_type, A1::size + 3> A2;  // OK,  A2 is A<int,5>

今、私はメンバーへのポインタで同じことをしたい:

struct Foo {
    int m;
    int r;
};

template<int Foo::*Mem>
struct B {
   static int Foo::* const mp;
};

template<int Foo::*Mem>
int Foo::* const B<Mem>::mp = Mem; // Save pointer to member

しかし、私はエラーが発生します。

typedef B<&Foo::m> B1;
typedef B<B1::mp>  B2;  // DOES NOT WORK

最後の行を機能させるには? または類似の結果を得る方法は?

ノート。私はそれがうまくいかないことを知っています。C++ 標準へのリンクは必要ありません。回避策が必要です。

4

4 に答える 4

1

C++ 標準 5.19/2 に従って動作しないはずです。

他の式は、非ローカル静的オブジェクトの初期化(3.6.2)の目的でのみ定数式と見なされます。 そのような
定数 式は 、次のいずれかに評価されるものとし ます 。完全なオブジェクト型のアドレス定数式、プラスまたはマイナスの整数定数式、 または — メンバ定数式へのポインタ






これは元の質問に対する答えではありませんが、この間違ったステートメントに対する答えです。

于 2009-12-16T18:30:11.663 に答える
0

マイクは、コンパイルする必要があることは正しいです。これはVSのバグです。

于 2009-12-16T17:21:40.433 に答える
0

そんなものは無いことに驚きました。少なくとも予想される場所では、たとえば次のようになります。

ここには何もありませんhttp://www.boost.org/doc/libs/1_60_0/libs/type_traits/doc/html/index.htmlここにもhttp://en.cppreference.com/w/cpp/types/ の近くにはありませんis_member_pointer

このhttp://www.boost.org/doc/libs/1_60_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.htmlおよびこのhttp://en.cppreference.com/w/cpp/に基づくtypes/is_member_pointer独自のロールを作成するのは難しくありません。

#include<type_traits> // std::is_pointer_member

template<class MP> struct member_pointer_traits_helper;

template< class T, class U >
struct member_pointer_traits_helper<T U::*>{
    using class_type = U;
    using declaration_type = T;
};

template< class MP >
struct member_pointer_traits : 
member_pointer_traits_helper<typename std::remove_cv<MP>::type> {};

struct B{
    int b;
};

int main(){
    using std::same;

    static_assert(std::is_member_pointer<int B::*>::value == true, "");
    static_assert(is_same<member_pointer_traits<int B::*>::class_type, B>{}, "");
    static_assert(is_same<member_pointer_traits<int B::*>::declaration_type, int>{}, "");
    static_assert(is_same<member_pointer_traits<decltype(&B::b)>::declaration_type, int>{}, "");
//  static_assert(is_same<member_pointer_traits<double>::class_type, B>{}, ""); // error
}

名前が最適かどうかはわかりません。また、非メンバー ポインターに適用すると、コンパイラ エラーが発生します (この設計はhttp://www.boost.org/doc/libs/1_60_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.htmlからコピーされます)。 )、別の方法として、型を返すこともできます(クラスまたはメンバー型にすることはできないvoidため、これは明らかに失敗の戻り値です)。void

(いくつかの小さな変更により、C++98 で使用できます。より明確にするために C++11 を使用しました。)

于 2016-05-10T11:41:08.290 に答える
0

完全な答えではありませんが、Mem に直接アクセスできますか?

すなわち: B1::mp の代わりに B1::Mem。

直接アクセスするのではなく、型の場合は通常、テンプレート名を typedef するため、標準では許可されていないと確信していますが、技術的には許可する可能性があります (何が意味するかはわかりません)。実行時に行われる静的メンバーの初期化が必要なため(間違っている場合は修正してください)、ソリューションが機能しない可能性が高いため、コンパイル時に必要なようにアクセスできません。

適切な回避策が可能かどうかを確認するために、trait/policy クラスで何をしようとしているのかの全体像を教えてください。

于 2009-12-17T14:56:39.583 に答える