8

VC++ の少し古いバージョン 2010 にコードを移植する際に問題があります。

この問題は、VC でのマップの実装が原因で発生します。これにより、派生した a の基本変換pointer-to-membernon-type-argument必要になります。

#include <map>
#include <algorithm>

template <typename MapValueType, int MapValueType::*var>
bool f (MapValueType const & v);

int main ()
{
  typedef std :: map<int, int> MapType;
  MapType m;
  std :: find_if (m.begin ()
      , m.end ()
      , f<MapType::value_type, & MapType::value_type::second> );
}

次のメッセージが生成されます。

base のポインターからメンバーへの標準変換は、テンプレート引数 file.cc(x) には適用されません: エラー C2973: 'f': 無効なテンプレート引数 'int std::_Pair_base<_Ty1, _Ty2>::* '

value_typeしたがって、 inの実装はstd::map基本クラスにペアがあるようです。

これを解決し、を維持する方法についてのアイデアはpointer-to-memberありnon-type-argumentますか?

メンバーを持つfように構造を変更する唯一のオプションですか?functorpointer-to-member

4

2 に答える 2

4

メンバーへのポインターを非型テンプレートのパラメーター/引数として保持することを主張するのはなぜですか?

とにかく、Visual Studio 2010またはコンパイラのいずれかに制限できる場合は、これを使用できると思いますdecltype()

template <typename Class, typename Type>
Class
get_class_type (Type Class:: *);
//...
it = std::find_if(m.begin(), m.end(),
    f<decltype(get_class_type(&MapType::value_type::second)), &MapType::value_type::second>);
于 2013-01-21T14:26:40.557 に答える
3

コードが IMO をコンパイルする必要がある場合 (GCC 4.7.2 および Clang 3.2 でコンパイルする必要がある場合)、あなたの設計は不必要に複雑であると思います。Apairにはメンバー変数が 2 つしかないため、最初または 2 番目のいずれかにアクセスします。

ファンクター オブジェクトの必要性もわかりません。ブール型のテンプレート引数を使用して、コードがメンバー変数firstまたはsecondメンバー変数で機能するかどうかを判断するだけです。可能性は次のとおりです。

#include <map>
#include <algorithm>

template <typename MapValueType, bool first>
bool f (MapValueType const & p)
{
    auto& v = (first) ? p.first : p.second;
    // ... do your work on v ...    
}

int main ()
{
    typedef std :: map<int, int> MapType;
    MapType m;

    // Will work on the `first` member
    std::find_if(m.begin (), m.end (), f<MapType::value_type, true>);

    // Will work on the `second` member
    std::find_if(m.begin (), m.end (), f<MapType::value_type, false>);
}

クライアントコードもf()関数内のコードも本当に変更できない場合は、次の VS2010 固有のハックを使用できます。

// Add "_MyBase" here... works, but ugly IMO
template <typename MapValueType, int MapValueType::_Mybase::* var>
bool f(MapValueType const & v);

// And the client side could stay unchanged...
int main ()
{
    typedef std :: map<int, int> MapType;
    MapType m;
    std::find_if(
        m.begin(), 
        m.end (), 
        f<MapType::value_type, &MapType::value_type::second>
        );
}

最後に、コードを他のプラットフォームコンパイルする必要があり、関数とクライアント コードの変更不可に関するすべての制約が引き続き適用さ_Mybase::れる場合は、VS2010 では に、他のコンパイラでは空の文字列に展開するプリプロセッサ マクロを定義できます。

于 2013-01-21T14:38:20.167 に答える