下面的代码段有效。但是,它有点难看,因为它使用静态方法将方法调用包装到谓词。
换句话说,我想替换:
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
}
ataylor的建议std::mem_fun_ref()
要求gcc 4.6.1和其他编译器不完全符合最新标准
#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 ));
}
答案 0 :(得分:3)
c.remove_if_true( std::bind( &Value::isOdd, _1 ) );
答案 1 :(得分:3)
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);
}
答案 2 :(得分:2)
您可以使用std::mem_fn_ref
打包isOdd
:
c.remove_if_true( std::mem_fun_ref(&Value::isOdd) );
答案 3 :(得分:1)
最好的方法是使用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 );