绑定类型别名

std::bind with type alias

本文关键字:别名 类型 绑定      更新时间:2023-10-16

我试图使用std::transformmap的值复制到vector。听了这个回答,我设法去做了。在寻找方法的过程中,我了解到了select2nd。因此,我试图使用std::bind实现"select2 -like"操作。但是,当定义select2nd别名时,我得到:

test.cpp:9:19: error: expected type-specifier
 using select2nd = std::bind(&T::value_type::second, std::placeholders::_1);
                   ^
test.cpp: In function ‘int main()’:
test.cpp:29:64: error: ‘select2nd’ was not declared in this scope
     std::transform(m.begin(), m.end(), std::back_inserter(v2), select2nd);

这是我想出来的代码片段:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <functional>
#include <map>
#include <vector>
template <typename T>
using select2nd = std::bind(&T::value_type::second, std::placeholders::_1);
using std::placeholders::_1;
void printn(int i) {
    std::cout << i << " ";
}
int main() {
    std::map<int, int> m;
    std::vector<int> v1, v2;
    for (auto &i : { 0, 1, 2, 3, 4 }) {
        m[i] = rand();
    }
    // Works
    std::transform(m.begin(), m.end(), std::back_inserter(v1),
            std::bind(&std::map<int, int>::value_type::second, _1));
    // Doesn't
    std::transform(m.begin(), m.end(), std::back_inserter(v2), select2nd);
    std::for_each(v1.begin(), v1.end(), std::bind(printn, _1));
    std::cout << std::endl;
    std::for_each(v2.begin(), v2.end(), std::bind(printn, _1));
    std::cout << std::endl;
    return 0;
}

为什么第一个transform可以工作,而第二个不行?如何将别名参数化为std::bind ?

这应该可以工作,但不是更好:

template <typename T>
decltype(std::bind(&T::value_type::second, std::placeholders::_1)) select2nd(T m) {
    return std::bind(&T::value_type::second, std::placeholders::_1);
}
// ....
std::transform(m.begin(), m.end(), std::back_inserter(v2), select2nd(m));
// ....

下面是另一个不需要参数的选择:

template <typename T>
    decltype(std::bind(&T::value_type::second, std::placeholders::_1)) select2nd() {
        return std::bind(&T::value_type::second, std::placeholders::_1);
    }

你可以这样使用:

std::transform(m.begin(), m.end(), std::back_inserter(v2), 
                                select2nd<std::map<int, int>>());

或:

std::transform(m.begin(), m.end(), std::back_inserter(v2), 
                                select2nd<decltype(m)>());