在vc2010中为地图值类型创建指向成员的指针

Ric*_*den 8 c++ visual-c++

我们将代码移植到VC++的旧版本2010中有一个问题.

问题是通过地图的在VC执行,这导致在派生到基本转换的引起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> );
}
Run Code Online (Sandbox Code Playgroud)

生成以下消息:

从指针到基础成员到派生指针到成员的标准转换不适用于模板参数file.cc(x):错误C2973:'f':无效模板参数'int std :: _ Pair_base <_Ty1, _Ty2> ::*'

所以似乎value_typein 的实现std::map具有基类中的对.

关于如何解决这个任何想法保持pointer-to-member为一个non-type-argument

是我们改变结构,使唯一的选择ffunctor用一个成员pointer-to-member

And*_*owl 3

假设您的代码应该编译 IMO(并且它在 GCC 4.7.2 和 Clang 3.2 上编译),我相信您的设计不必要地复杂。Apair只有两个成员变量,因此您将访问第一个或第二个。

我也不认为需要函子对象:只需使用布尔模板参数来确定代码是否适用于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>);
}
Run Code Online (Sandbox Code Playgroud)

如果您确实无法更改客户端代码或函数内的代码f(),那么您可以采用以下针对 VS2010 的 hack:

// 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>
        );
}
Run Code Online (Sandbox Code Playgroud)

最后,如果您的代码必须在其他平台上编译,并且对函数和客户端代码的不可修改性的所有限制仍然存在,那么您可以定义一个预处理器宏,该宏_Mybase::对于 VS2010 扩展为,对于其他编译器扩展为空字符串。