【问题标题】:Is there a standard C++ function object for taking apart a std::pair?是否有一个标准的 C++ 函数对象用于拆分 std::pair?
【发布时间】:2010-09-27 05:25:52
【问题描述】:
有谁知道是否存在用于访问 std::pair 元素的事实上的标准(即 TR1 或 Boost)C++ 函数对象?在过去的 24 小时内,我曾两次希望有类似 keys 的 Perl 哈希函数。例如,最好在 std::map 对象上运行 std::transform 并将所有键(或值)转储到另一个容器。我当然可以编写这样一个函数对象,但我更愿意重用一些吸引眼球的东西。
【问题讨论】:
标签:
c++
boost
std
tr1
std-pair
【解决方案1】:
boost::bind 就是你要找的。p>
boost::bind(&std::pair::second, _1); // returns the value of a pair
例子:
typedef std::map<std::string, int> map_type;
std::vector<int> values; // will contain all values
map_type map;
std::transform(map.begin(),
map.end(),
std::back_inserter(values),
boost::bind(&map_type::value_type::second, _1));
【解决方案2】:
从您提出问题的方式来看,我不确定这是一个正确的回答,但请尝试boost::tie(Boost::tuple 库的一部分)。它也适用于std::pairs。
【解决方案3】:
boost::bind 通常用于调整 std::map 容器以用于算法。 Here 就是一个例子:
void print_string(const std::string& s) {
std::cout << s << '\n';
}
std::map<int,std::string> my_map;
my_map[0]="Boost";
my_map[1]="Bind";
std::for_each(my_map.begin(), my_map.end(),
boost::bind(&print_string, boost::bind(
&std::map<int,std::string>::value_type::second,_1)));
【解决方案4】:
如何使用不同容器的组合。
例如,当我想将向量划分为包含在补充地图中的项目和未包含在补充地图中的项目时,我使用了以下内容:
typedef int DWORD;
typedef std::pair<std::string, bool> user_info;
typedef std::map<DWORD, user_info> USER_MAP;
typedef std::vector<DWORD> VEC_STAFF;
VEC_STAFF::iterator it = std::partition(Staff.begin(), Staff.end(), (bind(&USER_MAP::find, m_Users, _1) != m_Users.end()));
现在我有第二个问题 - 在应用程序运行期间,user_info 的状态布尔值可能会发生变化,稍后我想用状态布尔值为 true 而不仅仅是包含在补充地图。
但是,我似乎在访问嵌套对的第二项时遇到了问题。
我尝试了以下方法,但似乎无法访问嵌套对!
CActiveUsers::VEC_STAFF::const_iterator itCurEnd = partition(Staff.begin(), Staff.end(), bind(&USER_MAP::value_type::second::second, bind(&USER_MAP::find, &m_Users, _1)) == true);
【解决方案5】:
看看 boost::adaptors。有预定义的适配器用于迭代映射键或值而不将它们复制到中间容器。
【解决方案6】:
没有建议的一个选项是std::tr1::get。请参阅n1745 的第 6.1.2 和 6.1.4 节。
std::pair< std::string, int > p( "foo", 1729 );
int hr = std::tr1::get< 1 >( p );
在您提到的map 提取案例中,绝对不像bind 那样容易使用,但仍然值得了解。改编 Johannes 的代码:
typedef std::map<std::string, int> map_type;
std::vector<int> values; // will contain all values
map_type map;
// std::tr1::get is overloaded so we need to help the compiler choose
const map_type::value_type::second_type & (*get)( const map_type::value_type & ) =
&std::tr1::get< 1, map_type::value_type::first_type, map_type::value_type::second_type >;
std::transform(map.begin(),
map.end(),
std::back_inserter(values),
get);