【发布时间】:2019-10-18 05:00:17
【问题描述】:
我有一组数据需要按照用户在运行时决定的标准进行排序。
理想情况下,这个排序标准必须作为参数传递给函数,例如:
void mainFunction(
InputData const &inputData,
OutputData &outputData,
BaseSortingCriteria const &compareFunctor)
{
/* The data is sorted by this map using the custom provided functor as criteria */
std::map<InputDataType, ValueType, BaseSortingCriteria> sortedSets(compareFunctor);
...
}
为此,我创建了一个表示基本条件的虚拟函子,例如:
struct VirtualSortingCriteria
{
virtual bool operator()(
const InputDataType &var1,
const InputDataType &var2) const = 0;
}
为了保持一个通用接口,一个基本函子,它只是执行一个在构造过程中传递的“真实”函子:
struct BaseSortingCriteria
{
BaseSortingCriteria(
std::shared_ptr<const VirtualSortingCriteria> pCompareFunctor) :
m_realCompareFunctor(pCompareFunctor)
{
}
bool operator()(
const InputDataType &var1,
const InputDataType &var2)
{
return m_realCompareFunctor->operator()(var1, var2);
}
private:
/** Pointer to the real functor to be used. */
std::shared_ptr<const VirtualSortingCriteria> const m_realCompareFunctor;
}
我已经定义了几个“真正的”函子来测试:
struct RealFunctorVersionA final : public VirtualSortingCriteria
{
bool operator () (
InputDataType const &var1,
InputDataType const &var2) const;
};
struct RealFunctorVersionB final : public VirtualSortingCriteria
{
bool operator () (
InputDataType const &var1,
InputDataType const &var2) const;
};
实际使用这些不同排序标准的代码如下所示:
std::shared_ptr<VirtualSortingCriteria> cmpFunctor;
switch(userSelectedSortingCriteria)
{
case CRITERIA_A:
cmpFunctor.reset(new RealFunctorVersionA);
break;
case CRITERIA_B:
cmpFunctor.reset(new RealFunctorVersionB);
break;
default:
break;
}
BaseSortingCriteria baseCmpFunctor(cmpFunctor);
mainFunction(inputData, outputData, baseCmpFunctor);
所有这些都可以正常工作。但是,我认为实现我想要的东西太复杂了,而且我感觉必须使用多态特性意味着“真正的”函子不能再被内联,导致可能(虽然我还没有测量) 性能损失。
我不确定这是否可以使用模板以更简单的方式解决(因为函子选择是在运行时完成的)。
有什么建议吗?还是我只是想多了这个问题,这是一个可以接受的解决方案?性能怎么样?
我不在mainFunction() 接口中使用纯C 风格的函数(bool (*)(InputDataType const &var1, InputDataType const &var2)) 来访问函子提供的额外功能,例如状态、构造参数等。
非常感谢您的建议。
【问题讨论】:
-
std::map<InputDataType, ValueType, std::function<bool(const IntputDataType&, const InputDataType&)>>? -
@MilesBudnek 你应该这样回答。 OP 可能知道也可能不知道如何正确使用
std::function。其他读者也是如此。 -
对此要非常小心。如果您在地图中有元素后更改排序方法,那么您就有了 UB。
-
您可以为所有可能的排序器使用
std::variant和std::map,并通过访问者访问它,然后代码将被内联。但它会更复杂,更不灵活,所以你最好在需要时进行衡量。
标签: c++ polymorphism functor stdmap