C++ std::在运行时设置选择较少或较大的比较器

C++ std::在运行时设置选择较少或较大的比较器,c++,stl,set,predicate,C++,Stl,Set,Predicate,我重构了一些代码,发现有两个地方可以用相同的代码编写,除了一个地方的比较器是less,另一个地方是greater。比如: double MyClass::Function1(double val) { std::set<double, less<double> > s; // Do something with s } double MyClass::Function2(double val) { std::set<double, grea

我重构了一些代码,发现有两个地方可以用相同的代码编写,除了一个地方的比较器是
less
,另一个地方是
greater
。比如:

double MyClass::Function1(double val)
{
    std::set<double, less<double> > s;
    // Do something with s
}

double MyClass::Function2(double val)
{
    std::set<double, greater<double> > s;
    // Do the same thing with s as in Function1
}
double MyClass::Function1(double val)
{
std::集s;
//用手指做点什么
}
双MyClass::Function2(双val)
{
std::集s;
//对s执行与函数1相同的操作
}
所以我想做:

double MyClass::GeneralFunction(double val, bool condition)
{  
    if(condition)  
    {  
        // Select greater as comparator  
    }  
    else
    {  
        // Select less as comparator  
    }  

    set<double, comparator> s;  
    // common code
}
double MyClass::GeneralFunction(双val,布尔条件)
{  
如果(条件)
{  
//选择较大值作为比较器
}  
其他的
{  
//选择less作为比较器
}  
设置s;
//通用代码
}
我通过使用自定义比较器函数使其正常工作,如下所示:

bool my_greater(double lhs, double rhs)
{
    return lhs > rhs;
}

bool my_less(double lhs, double rhs)
{
    return lhs < rhs;
}

double MyClass::GeneralFunction(double val, bool condition)
{ 
    typedef bool(*Comparator) ( double,  double);
    Comparator comp = &my_less;
    if (condition)
    {
        comp = &my_greater;
    }

    std::set<double, Comparator > s(comp);  

    //....
}
bool my_更大(双左、双右)
{
返回左侧>右侧;
}
bool my_less(双左、双右)
{
返回左侧<右侧;
}
double MyClass::GeneralFunction(双val,布尔条件)
{ 
typedef bool(*比较器)(双精度,双精度);
比较器comp=&my\u less;
如果(条件)
{
comp=&my\u更大;
}
标准:集合s(comp);
//....
}
但是我想使用内置的。问题是我不知道如何声明比较器并为其分配内置谓词

任何帮助都将不胜感激。

为什么不这样做呢

template <typename Compare>
double MyClass::GeneralFunction(double val)
{
    std::set<double, Compare> s;

    //....
}
模板
双MyClass::GeneralFunction(双val)
{
std::集s;
//....
}

模板参数的模板选择不是C++处理得很好的。通过让调用者提供模板参数,尽可能多地推进编译阶段

然后,如果您确实希望在运行时选择一个包装器,则可以提供包装器:

double MyClass::GeneralFunction(double val, bool condition)
{
    return condition ?
        GeneralFunction<std::greater<double> >(val) :
        GeneralFunction<std::less   <double> >(val);\
}
double MyClass::GeneralFunction(双val,布尔条件)
{
返回条件?
通用功能(val):
通用函数(val)\
}

您真的需要运行时检查吗

template <class Comp> double MyClass::Function(double val)
{
    std::set<double, Comp > s;
    // Do something with s
}
template double MyClass::Function(double val)
{
std::集s;
//用手指做点什么
}
即使你这样做了,你仍然可以使用

double MyClass::Function(double val, bool comp)
{
   return comp ? Function<std::less<double> >(val) : Function<std::greater<double> >(val);
}
double MyClass::函数(双val,bool comp)
{
返回补偿函数(val):函数(val);
}
只需使用

std::set<double, std::function<bool(double,double)>>

问题是,您无法在此时选择比较器的类型 tuntime和
std::less
std::greater
具有不相关的类型。 类似地,用
std::less
作为比较器实例化的
std::set
具有与on无关的类型,该类型使用
std::greater
实例化。有 有几种可能的解决方案,但最简单的(也是唯一的一种) 涉及内在性、虚拟功能和动态分配)的研究也在进行中 你正在做的事情的台词:

class SelectableCompare
{
    bool myIsGreater;
public:
    SelectableCompare( bool isGreater ) : myIsGreater( isGreater ) {}
    bool operator()( double d1, double d2 ) const
    {
        static std::less<double> const less;
        return myIsGreater
            ? less( d2, d1 )
            : less( d1, d2 );
    }
};
,用于不同比较的相当明显的派生类,以及 管理内存的包装器:

class ComparatorWrapper
{
    std::shared_ptr<Comparator> myComparator;
public:
    ComparatorWrapper( Comparator* newed_comparator )
        : myComparator( newed_comparator )
    {
    }
    bool operator()( double d1, double d2 ) const
    {
        return myComparator->isLessThan( d1, d2 );
    }
};
类ComparatorWrapper
{
std::共享\u ptr myComparator;
公众:
比较器包装器(比较器*新比较器)
:myComparator(新的\u比较器)
{
}
布尔运算符()(双d1,双d2)常量
{
返回myComparator->isLessThan(d1、d2);
}
};
对于您所需要的二进制选择来说,这无疑是过分的,但可能是 如果有更多的选择,则适当;e、 g.a
设置
可能是
在许多不同字段中的一个字段上排序(所有字段都是不同类型的)。

+1用于
std::function
。关于在使用集合时意外更改顺序的风险:任何标志都应该是函数对象的私有成员,这将极大地降低风险。std::function部分是我实际要问的,但我认为MSalters的答案是更好的解决方案。谢谢!我实际上不需要运行时检查,所以我可以在调用者中选择比较器。
class SelectableCompare
{
    bool myIsGreater;
public:
    SelectableCompare( bool isGreater ) : myIsGreater( isGreater ) {}
    bool operator()( double d1, double d2 ) const
    {
        static std::less<double> const less;
        return myIsGreater
            ? less( d2, d1 )
            : less( d1, d2 );
    }
};
class Comparator
{
public:
    virtual ~Comparator() {}
    virtual bool isLessThan( double d1, double d2 ) const = 0;
};
class ComparatorWrapper
{
    std::shared_ptr<Comparator> myComparator;
public:
    ComparatorWrapper( Comparator* newed_comparator )
        : myComparator( newed_comparator )
    {
    }
    bool operator()( double d1, double d2 ) const
    {
        return myComparator->isLessThan( d1, d2 );
    }
};