簡體   English   中英

如何重構容器以直接使用謂詞方法?

[英]how can I refactor a container to use a predicate method directly?

以下代碼段有效。 但是,這有點丑陋,因為它使用靜態方法將方法調用包裝到謂詞。

換句話說,我想替換為:

c.remove_if_true( Value::IsOdd );   // static method

用類似的東西

c.remove_if_true( Value::isOdd );   // member method

間接訪問的級別應該少一些,希望最終的代碼會更清晰。

如何重構代碼以直接調用isOdd()而不需要通過靜態方法包裝器?

但是,如果此實現可以使我清楚地實現此代碼,則也請告知我。 TIA。

#include <vector>
#include <functional>

template< typename T >
class MyContainer
{
public:
    typedef std::function<bool(const T& t)>   PREDICATE;

public:
    void remove_if_true( PREDICATE predicate )
    {
        // NOTE: use implementation from KennyTM's answer below
    }
private:
    std::vector< T >  m_vec;
};

class Value
{
public:
    Value( int i ) : m_i( i ) { }
    bool isOdd() const { return m_i%2==1; }
    static bool IsOdd( const Value& v ) { return v.isOdd(); }
private:
    int m_i;
};


int main()
{
    MyContainer<Value> c;

    c.remove_if_true( Value::IsOdd );  // would like to replace with Value::isOdd here
}

使用KennyTM的答案的解決方案

gcc 4.6.1和其他編譯器要求的ataylor建議std::mem_fun_ref()並非最新標准的最新版本

#include <vector>
#include <algorithm>
#include <functional>

template< typename T >
class MyContainer
{
public:
    typedef std::const_mem_fun_ref_t<bool, T>  PREDICATE;

public:
    void remove_if( PREDICATE predicate )
    {
        auto old_end = m_vec.end();
        auto new_end = std::remove_if(m_vec.begin(), old_end, predicate);
        m_vec.erase(new_end, old_end);
    }
private:
    std::vector< T >  m_vec;
};

class Value
{
public:
    Value( int i ) : m_i( i ) { }
    bool isOdd() const { return m_i%2==1; }
private:
    int m_i;
};


int main()
{
    MyContainer<Value> c;

    c.remove_if( std::mem_fun_ref( &Value::isOdd ));
}

c.remove_if_true( std::bind( &Value::isOdd, _1 ) );

c.remove_if_true( std::mem_fn(&Value::isOdd) );

順便說一句,有什么理由需要避免std::remove_if嗎?

void remove_if_true(PREDICATE predicate)
{
    auto old_end = m_vec.end();
    auto new_end = std::remove_if(m_vec.begin(), old_end, predicate);
    m_vec.erase(new_end, old_end);
}

您可以使用std::mem_fn_ref包裝isOdd

c.remove_if_true( std::mem_fun_ref(&Value::isOdd) );

最好的使用lambdas的方法:

c.remove_if_true( [] (const Value & v) { return v.get() % 2 == 0; } );

或更自我評論:

auto isOdd = [] (const Value & v) { return v.get() % 2 == 0; };
c.remove_if_true( isOdd );

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM