我们将代码移植到VC++的旧版本2010中有一个问题.
问题是通过地图的在VC执行,这导致在派生到基本转换的引起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> );
}
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?
是我们改变结构,使唯一的选择f是functor用一个成员pointer-to-member?
假设您的代码应该编译 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 扩展为,对于其他编译器扩展为空字符串。