gpt4 book ai didi

c++ - 处理值和引用语义的模板类

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:46:53 26 4
gpt4 key购买 nike

我一直在使用二进制堆处理优先级队列,并为此开发了一个类,如下所示。

#include <iostream>
#include <type_traits>

template<class T, int N>
class BinaryHeap{

template<class T1>
class has_less_than_operator
{
private:
class no{};
template<class X>
static auto has(X&& t) -> decltype (t.operator < (t));

static no has(...);
public:
enum {
value = !std::is_same<
decltype(has( std::declval<T1>() )),
no>::value
};
};

static_assert(std::is_copy_assignable<T>::value &&
std::is_copy_constructible<T>::value,
"Must be copy assignable and constructable");
public:
BinaryHeap() : used_(0){

}

BinaryHeap(BinaryHeap const& other) = default;

BinaryHeap& operator = (BinaryHeap const& other) = default;

inline T& max(){
return elements_[FIRST];
}

inline T const & max() const{
return elements_[FIRST];
}

void insert(T const& item){
elements_[++used_] = item;
swim(used_);
}

inline bool full() const{
return used_ == N;
}

void deleteMax(){
std::swap(elements_[used_],elements_[FIRST]);
sink(FIRST);
elements_[used_--] = T();
}

private:

template<class T1>
class has_dereference_operator
{
private:
class no{};
template<class X>
static auto has(X&& t) -> decltype (t.operator * ());

static no has(...);
public:
enum {
value = !std::is_same<
decltype(has( std::declval<T1>() )),
no>::value
};
};



inline bool parent_less(int position,std::integral_constant<int,0> i){
return elements_[ position / 2] < elements_[position];
}

inline bool parent_less(int position,std::integral_constant<int,1> i){
return *(elements_[ position / 2]) < *(elements_[position]);
}

void swim(int position){
while(position > 1 && parent_less(position,std::integral_constant<int, has_dereference_operator<T>::value>()))
{
std::swap(elements_[ position / 2], elements_[position]);
position /= 2;
}
}

inline int which_less(int p1, int p2, std::integral_constant<int,0> i){
return (elements_[ p1] < elements_[p2]) ? p1 : p2;
}

inline int which_less(int p1, int p2, std::integral_constant<int,1> i){
return (*(elements_[ p1]) < *(elements_[p2])) ? p1 : p2;
}

inline int which_greater(int p1, int p2, std::integral_constant<int,0> i){
return (elements_[ p1] < elements_[p2]) ? p2 : p1;
}

inline int which_greater(int p1, int p2, std::integral_constant<int,1> i){
return (*(elements_[ p1]) < *(elements_[p2])) ? p2 : p1;
}

void sink(int position){
while(position * 2 <= used_){
int first = position * 2;
if(first > used_) break;

int greater_child = which_greater(first, first + 1, std::integral_constant<int, has_dereference_operator<T>::value>());
int lesser = which_less(greater_child, position, std::integral_constant<int, has_dereference_operator<T>::value>());
if(lesser == greater_child)
break;

std::swap(elements_[greater_child], elements_[position]);
position = greater_child;
}
}

inline int current_position() const{
return used_ + 1;
}

static const int MAX = N + 1;
static const int FIRST = 1;
static const int LAST = N;
T elements_[MAX];
int used_;
};

int main(int argc, const char * argv[])
{

BinaryHeap<int, 10> b;

b.insert(1);
b.insert(20);
b.insert(21);
b.insert(3);
b.insert(2);

std::cout << "Max: " << b.max() << std::endl;

b.deleteMax();

std::cout << "Max: " << b.max() << std::endl;

return 0;
}

虽然我有这个工作,但我需要处理比较的差异,比如指针/共享指针,比如使用解引用运算符和值,只是按原样使用它们。我目前正在使用 SFINAE 根据该类是否具有运算符 * 来执行此操作。

这是实现这一目标的正确方法吗?

布莱尔

最佳答案

像这样使用启发式方法的问题在于,它并不总是代码的客户端希望您执行的操作,而且您没有提供更改行为的方法。有一天,客户可能想使用您的类来存储指针并实际使用 std::less<T> 对它们进行排序。而不是取消引用(例如 BinaryHeap<void*,32>)。即使使用非指针,客户也可能只是想要一个与 < 强加的顺序不同的顺序。 .

当标准库需要进行比较时,它通常使用std::less<T>默认情况下,但为客户端提供了一种覆盖该选择的方法(例如 std::priority_queue std::sort )。如果我正在编写您的类(class),我会通过默认为 std::less<T> 的比较运算符对其进行参数化就像标准库一样。我还会提供一个方便的取消引用比较器模板,使使用指针的客户可以轻松地按指针进行排序。

关于c++ - 处理值和引用语义的模板类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20953093/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com