我正在尝试构建一个具有可自定义比较谓词的关联容器,并且我在内部使用一个集合来存储一些数据。它应该非常简单,我只需要传递谓词即可:
template <typename T, typename TComparePredicate = std::less<T>>
class MyContainer
{
public:
MyContainer(const TComparePredicate& predicate = TComparePredicate()) : _internalSet(predicate) { ... }
...
private:
std::set<T, TComparePredicate> _internalSet;
};
不幸的是,我的真实案例更为复杂。我需要在集合中存储其他数据(不要问为什么,在这种情况下这是有意义的),所以我的代码看起来更像是这样的:
template <typename T, typename V, typename TComparePredicate = std::less<T>>
class MyContainer
{
public:
MyContainer(const TComparePredicate& predicate = TComparePredicate()) : _internalSet(???) { ... }
...
private:
std::set<std::pair<T, V>, ???> _internalSet;
};
我仍然需要仅考虑
T
值来对集合进行排序,因此我的简单解决方案是创建一个函子来存储真实谓词并分派对其的调用:
template <typename T, typename V, typename Predicate>
struct PairForwardingFunctor
{
PairForwardingFunctor(const Predicate& predicate = Predicate()) : _predicate(predicate) { }
bool operator()(const std::pair<T, V>& lhs, const std::pair<T, V>& rhs) { return _predicate(lhs.first, rhs.first); }
private:
Predicate _predicate;
};
但我对这个解决方案感到不安。我还没有对此进行编译器探索(如果它甚至可以到达那里),但我有一种感觉,存在一定程度的间接性不可优化。
有更好的方法吗?
我不确定您是否可以跳过间接级别,因为您必须为
Compare
的 std::set
模板参数提供特定类型。
您可以通过将此比较器放入您的类中来使您的解决方案不那么冗长,并避免使用私有成员:
#include <set>
#include <iostream>
template <typename T, typename V, typename TComparePredicate = std::less<T>>
struct MyContainer
{
struct PairForwardingFunctor
{
bool operator() (const std::pair<T, V>& lhs, const std::pair<T, V>& rhs) const
{ return TComparePredicate{} (lhs.first, rhs.first); }
};
std::set<std::pair<T,V>, PairForwardingFunctor> _internalSet;
auto begin() const { return _internalSet.begin(); }
auto end () const { return _internalSet.end (); }
};
int main()
{
MyContainer<int,double> c = {{
{ 5, 3.14},
{-3, 2.71},
{ 2, 1.61}
}};
for (auto x : c) { std::cout << x.first << "\n"; }
}
注意:我在这里使用了一个带有内部
_internalSet
公共的结构,以便使用大括号初始化来获得更简单的代码片段。