【发布时间】:2018-11-14 16:03:57
【问题描述】:
提前道歉。我很难为这个问题找到正确的措辞......
作为练习,我正在研究一个固定大小的优先级队列,该队列丢弃大于最大值的对象(用于查找 X 最小对象的队列)并丢弃小于最小值的对象(用于持有最大 X 的队列对象)。问题是是否有办法在编译时达到比较器的逻辑“对立面”。
请参阅下面代码中的注释行:
template <
typename T,
typename Container = std::vector<T>,
typename Compare = std::less<typename Container::value_type>>
class fixed_size_priority_queue : public std::priority_queue<T, Container, Compare>
{
typename Container::size_type maxSize;
using base = std::priority_queue<T, Container, Compare>;
public:
fixed_size_priority_queue(std::size_t size) : base(), maxSize(size)
{
base::c.reserve(size);
}
void push(T value)
{
if (base::size() < maxSize)
{
base::push(value);
}
// is there some way of arriving at compile-time opposite of 'comp'?
else if (!base::comp(base::top(), value))
{
while (base::size() >= maxSize)
{
base::pop();
}
base::push(value);
}
}
};
void test_fixedPriQueue()
{
using smallestInts = fixed_size_priority_queue<int>;
smallestInts fq(4);
fq.push(5);
fq.push(3);
fq.push(5);
fq.push(5);
fq.push(7);
fq.push(11);
fq.push(1);
fq.push(2);
}
int main(int argc, char const *argv[])
{
test_fixedPriQueue();
return 0;
}
我只是简单地使用了 not (!) 操作符来完成这项工作,但这是否会导致运行时成本(尽管非常小)?当我的班级使用Compare = std::less时,有没有办法到达std::greater_equal?
我希望使用std::not<Compare> 之类的东西,当Compare 模板参数为std::less 时,它会解析为std::greater_equal。这有意义吗?
** 编辑 **
尝试 sergeyA 的建议得到了我想要的结果:
template<typename T, typename Comparison>
struct logical_opposite
{
using op = void;
};
template <typename T>
struct logical_opposite<T, std::less<T>>
{
using op = std::greater_equal<T>;
};
template <typename T>
struct logical_opposite<T, std::greater<T>>
{
using op = std::less_equal<T>;
};
然后在priority_queue派生的类中,实例化逻辑相反的函数对象,推入队列时使用:
//...
typename logical_opposite<T, Compare>::op not_comp;
public:
fixed_size_priority_queue(std::size_t size) : base(), maxSize(size), not_comp()
//....
比较函子类型之间存在逻辑关系,我希望这种关系在 STL 中表达出来。
【问题讨论】:
-
即使会有一些微不足道的开销(优化可能没有),我看不出如果没有
!,你如何从less获得greater_equal。老实说,这似乎是教科书式的过早优化。 -
@YSC 我确实看到了这个,但注意到它已被弃用并且很快就会过时。
-
有一个很好的理由:自从 lambdas 以来它已经过时了。
-
您可以创建一个模板化特征,它将根据模板参数选择相反的版本,并指定每次转换。乏味,并且可能没有可量化的性能优势。
标签: c++ templates template-meta-programming