8

我们在将代码移植到稍微不那么旧的 VC++ 2010 版本时遇到了问题。

该问题是由 VC 中的 map 实现引起的,这导致需要 a 的派生到基础pointer-to-member转换non-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> );
}

生成以下消息:

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

因此,似乎 in 的实现在基类value_typestd::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只有两个成员变量,因此您将访问第一个或第二个。

我也不认为需要仿函数对象:只需使用布尔模板参数来确定代码是否应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>
        );
}

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

于 2013-01-21T14:38:20.167 回答