简体   繁体   English

成员变量和STL算法

[英]Member variables and STL algorithms

#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;
}

Is there a cleaner way to access a member variable then then using a member function like I have above? 是否有更简洁的方法来访问成员变量然后使用像我上面的成员函数? I know how to do it using tr1::bind, but I need to have C++03 compliant code without boost. 我知道如何使用tr1 :: bind来完成它,但是我需要没有boost的C ++ 03兼容代码。

It's absolutely unclean to need an accessor function in order to do that. 为了做到这一点,需要一个访问器功能是绝对不洁净的。 But that's the current C++. 但那是当前的C ++。

You could try using boost::bind , which does the trick quite easily, or iterate the vector explicitly, using a for( vector<int>::const_iterator it = v.begin(); .....) loop. 你可以尝试使用boost::bind ,它很容易做到这一点,或者使用for( vector<int>::const_iterator it = v.begin(); .....)循环显式迭代向量。 I find the latter often resulting in clearer code when the creation of the functor becomes too much a hassle. 当发现仿函数的创建变得太麻烦时,我发现后者通常会产生更清晰的代码。

Or, shunning boost, create your own member-accessor shim function. 或者,避开提升,创建自己的member-accessor shim函数。

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 ) );

Like std::pair you could write access-or objects. 像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() );
}

Note: You should look at std::pair<T1,T2> 注意:您应该查看std :: pair <T1,T2>
And its accessors: std::select1st<T1> and std::select2nd<T2> 及其访问器:std :: select1st <T1>和std :: select2nd <T2>

The most clear way for me is boost::bind : 对我来说最明确的方法是boost::bind

#include <boost/bind.hpp>

...

transform(v.begin(), v.end(), back_inserter(is), bind( &Foo::i, _1 ) );

Surely you could create your own member access function, but I believe it will make your code less readable. 当然,您可以创建自己的成员访问功能,但我相信它会降低您的代码的可读性。 boost::bind is widely known library, so using it will make your code pretty readable and no need to read your helper functions (which could contain bugs occasionally) boost :: bind是众所周知的库,因此使用它将使您的代码具有可读性并且无需读取辅助函数(偶尔可能包含错误)

The second way I prefer is just to use for-loop (in this particular case): 我更喜欢的第二种方式是使用for循环(在这种特殊情况下):

for ( vector<Foo>::const_iterator it = v.begin(), it != v.end(); ++it )
    is.push_back( it->i );

May be it is not fashionable to use such simple loops, but they are very clear. 使用这种简单的循环可能不是时髦,但它们非常清晰。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM