假设我有一组(或映射)字符串,并且我想使用仅比较前 5 个字符的自定义比较器。所以“abcde”和“abcdef”在我的集合中是相同的。
using MySet = std::set<std::string, Cmp>;
Run Code Online (Sandbox Code Playgroud)
编写 Cmp 的最佳方式是什么?
明显的方法是这样的:
struct Cmp
{
bool operator()(const string& x, const string& y) const
{
return x.substr(0, 5) < y.substr(0, 5);
}
};
Run Code Online (Sandbox Code Playgroud)
问题是这段代码重复了.substr(0, 5)。在这个例子中它很短,但在一般情况下它可能会更长。我想避免这个重复的代码。
一般来说,给定类型T1, T2和函数T2 key(T1& const),我想要一组T1根据 进行比较的元素key(a) < key(b),其中比较 onT2已经明确定义。写这个的最好方法是什么?我考虑过编写一个新的class KeyBaseSet,但这对于我的单一用例来说是过度设计的。有什么方法可以使用stdBoost 来做到这一点吗?
我正在寻找类似于keyPython 中排序时的参数(https://docs.python.org/3/howto/sorting.html#key-functions),或compare `on` Haskell 中的习惯用法(https://stackoverflow.html)。 com/a/2788262/351105)。
您可以Cmp使用密钥策略进行自定义。最小的例子:
template<class Key>
struct Compare_on {
Compare_on(Key key = Key()) : key_(key)
{}
template<class T>
bool operator()(const T& x, const T& y) const {
return key_(x) < key_(y);
}
private:
Key key_;
};
struct First3 {
std::string_view operator()(const std::string& s) const {
return std::string_view(s).substr(0, 3);
}
};
// Example:
std::set<std::string, Compare_on<First3>> set;
set.insert("abc1");
set.insert("abc2");
Run Code Online (Sandbox Code Playgroud)
Compare_on可以通过使其成为透明比较器来改进:
template<class Key>
struct Compare_on {
using is_transparent = void;
Compare_on(Key key = Key()) : key_(key)
{}
template<class T1, class T2>
bool operator()(const T1& x, const T2& y) const {
return key_(x) < key_(y);
}
private:
Key key_;
};
struct First3 {
template<class T>
std::string_view operator()(const T& s) const {
return std::string_view(s).substr(0, 3);
}
};
Run Code Online (Sandbox Code Playgroud)
现在当我们这样做时
auto pos = set.find("abc");
Run Code Online (Sandbox Code Playgroud)
std::string不会为字符串文字构造临时值"abc"。