在vc2010中创建指向map值类型成员的指针

Create pointer to member for map value type in vc2010

本文关键字:类型 成员 指针 map vc2010 创建      更新时间:2023-10-16

我们在将代码移植到稍旧的vc++ 2010版本时遇到了问题。

这个问题是由VC中map的实现引起的,它导致non-type-argumentpointer-to-member的派生到基的转换是必需的:

#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> );
}

生成以下消息:

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

因此,value_typestd::map中的实现似乎在基类中有对。

关于如何解决这个保持pointer-to-member作为non-type-argument的想法吗?

我们唯一的选择是改变结构,使ffunctorpointer-to-member成员吗?

为什么坚持将指向成员的指针作为非类型模板形参/实参?

无论如何,我认为你可以使用这个,如果你可以限制在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>);

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

我也不认为需要一个函子对象:只需使用一个布尔模板实参来确定代码是在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特定的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>
        );
}

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