為這個模棱兩可的標題道歉。
這是我的代碼:
struct LowHigh
{
};
struct HighLow
{
};
template < class LookupScheme>
struct ladder_base
{
using value_type = price_depth;
using ladder_type = std::vector< value_type >;
template < class T >
struct lookup;
template <>
struct lookup< LowHigh >
{
static constexpr auto func = std::upper_bound< ladder_type::iterator, value_type >;
};
template <>
struct lookup< HighLow >
{
static constexpr auto func = std::lower_bound< ladder_type::iterator, value_type >;
};
void
insert(value_type v)
{
auto iter = lookup< LookupScheme >::func(std::begin(data_), std::end(data_), v);
data_.insert(iter, std::move(v));
}
protected:
std::vector< value_type > data_;
};
} // namespace detail
struct bid_ladder : detail::ladder_base< detail::HighLow >
{
};
struct offer_ladder : detail::ladder_base< detail::LowHigh >
{
};
我專注lookup::func于作為模板型別傳遞的方案。目前只有兩種可能的方案:LowHigh& HighLow。這具有確定基礎向量如何排序的效果。
有沒有更慣用/更簡潔的方式來表達這種邏輯?
uj5u.com熱心網友回復:
這些演算法將比較物件作為最后一個引數 - 因此您可以利用它來發揮自己的優勢。
template < class Compare >
struct ladder_base
{
using value_type = price_depth;
using ladder_type = std::vector< value_type >;
void
insert(value_type v)
{
auto iter = std::upper_bound(data_.begin(), data_.end(), v, Compare{} );
data_.insert(iter, std::move(v));
}
protected:
std::vector< value_type > data_;
};
然后使用ladder_base<std::less<>>or ladder_base<std::greater<>>,具體取決于您想要的排序順序。
請注意,std::lower_boundandstd::upper_bound不是反義詞,所以您的原文并不正確。lower_bound給你第一個元素>= x,upper_bound給你第一個元素> x。因此,從一個更改為另一個不會更改您的排序順序(兩者都需要遞增順序),只有比較物件會影響它。
例如:
std::vector<int> v = {1, 3, 5, 7};
auto i = std::lower_bound(v.begin(), v.end(), 3); // this is the 3
auto j = std::upper_bound(v.begin(), v.end(), 3); // this is the 5
請注意,向量是按升序排序的,但兩個呼叫都是格式正確的。如果您想要反向排序,則必須std::greater{}作為比較物件傳入(如我所示)。
但無論哪種方式,您都想使用std::upper_bound- 無論排序順序如何。
uj5u.com熱心網友回復:
做這類事情的慣用方法是讓模板引數包含要直接呼叫的代碼,而不是像你正在做的那樣通過標記型別間接呼叫。
請注意,在這一點上,您總是可以std::upper_bound直接作為模板引數傳遞。
此外,由于這是標記c 20的,因此您還可以理想地使用一個概念來約束可以傳遞給的型別ladder_base。
#include <concepts>
#include <vector>
using price_depth = int;
template<typename T>
concept LookupScheme = requires (const T& x, const std::vector<price_depth>& v) {
{x(v.begin(), v.end(), price_depth{})} -> std::same_as<decltype(v.begin())>;
};
namespace detail {
struct LowHigh {
template<typename ForwardIt, typename T>
decltype(auto) operator()(ForwardIt first, ForwardIt last, const T& value ) const {
return std::upper_bound(first, last, value);
}
};
struct HighLow {
template<typename ForwardIt, typename T>
decltype(auto) operator()(ForwardIt first, ForwardIt last, const T& value ) const {
return std::lower_bound(first, last, value);
}
};
template <LookupScheme Scheme>
struct ladder_base
{
using value_type = price_depth;
using ladder_type = std::vector< value_type >;
void insert(value_type v)
{
auto iter = Scheme::exec(std::begin(data_), std::end(data_), v);
data_.insert(iter, std::move(v));
}
protected:
std::vector< value_type > data_;
};
} // namespace detail
struct bid_ladder : detail::ladder_base< detail::LowHigh >
{
};
struct offer_ladder : detail::ladder_base< detail::HighLow >
{
};
您可以看到標準庫的排序容器中使用的相同方法,例如std::map<>'sCompare引數。
uj5u.com熱心網友回復:
template<class C>
auto lookup(C& c, value_type v) {
if constexpr(std::same_as<LookupScheme, LowHigh>)
return std::upper_bound(c.begin(), c.end(), v);
else if constexpr(std::same_as<LookupScheme, HighLow>)
return std::lower_bound(c.begin(), c.end(), v);
}
void insert(value_type v) {
auto iter = lookup(data_, v);
data_.insert(iter, std::move(v));
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/478090.html
