#include <vector>
#include <functional>
#include <algorithm>
using namespace std;
struct Foo
{
int i;
double d;
Foo(int i, double d) :
i(i),
d(d)
{}
int getI() const { return i; }
};
int main()
{
vector<Foo> v;
v.push_back(Foo(1, 2.0));
v.push_back(Foo(5, 3.0));
vector<int> is;
transform(v.begin(), v.end(), back_inserter(is), mem_fun_ref(&Foo::getI));
return 0;
}
是否有更简洁的方法来访问成员变量然后使用像我上面的成员函数?我知道如何使用tr1 :: bind来完成它,但是我需要没有boost的C ++ 03兼容代码。
答案 0 :(得分:8)
为了做到这一点,需要一个访问器功能是绝对不洁净的。但那是当前的C ++。
您可以尝试使用boost::bind
,这很容易实现,或使用for( vector<int>::const_iterator it = v.begin(); .....)
循环显式迭代向量。我发现后者通常会在创建仿函数时变得更加清晰。
或者,避开提升,创建自己的成员访问者填充功能。
template< typename T, typename m > struct accessor_t {
typedef m (T::*memberptr);
memberptr acc_;
accessor_t( memberptr acc ): acc_(acc){}
// accessor_t( m (T::*acc) ): acc_(acc){}
// m (T::*acc_);
const m& operator()( const T& t ) const { return (t.*acc_); }
m& operator()( T& t ) const { return (t.*acc_); }
};
template< typename T, typename m > accessor_t<T,m> accessor( m T::*acc ) {
return accessor_t<T,m>(acc);
}
...
transform( v.begin(), v.end(), back_inserter(is), accessor( &C::i ) );
答案 1 :(得分:3)
与std :: pair类似,您可以编写访问权限或对象。
#include <vector>
#include <algorithm>
struct Foo
{
int i;
double d;
};
struct GetI { int operator()(Foo const& o) const { return o.i;}};
struct GetD { double operator()(Foo const& o) const { return o.d;}};
int main()
{
std::vector<Foo> v;
std::vector<int> t;
std::transform(v.begin(), v.end(), std::back_inserter(t),GetI() );
}
注意:您应该查看std :: pair&lt; T1,T2&gt;
及其访问器:std :: select1st&lt; T1&gt;和std :: select2nd&lt; T2&gt;
答案 2 :(得分:2)
最明确的方式是boost::bind
:
#include <boost/bind.hpp>
...
transform(v.begin(), v.end(), back_inserter(is), bind( &Foo::i, _1 ) );
当然,您可以创建自己的成员访问功能,但我相信它会降低您的代码的可读性。 boost :: bind是众所周知的库,因此使用它将使您的代码具有可读性,无需读取辅助函数(偶尔可能包含错误)
我更喜欢的第二种方式是使用for-loop(在这种特殊情况下):
for ( vector<Foo>::const_iterator it = v.begin(), it != v.end(); ++it )
is.push_back( it->i );
使用这样简单的循环可能不太时髦,但它们非常清晰。