使用 std::sort 对自定义 类 的智能指针进行排序
Sorting smartpointer of custom classes with std::sort
我遇到的问题是,我有一个实现 operator<
.
的自定义 class 的 shared_ptr
向量
在堆栈上使用 class 时,我可以使用 std::sort 而无需将 Compare
指定为排序参数。但是当然,当我使用 shared_ptr
时,它(显然我认为)会尝试对指针而不是对象本身进行排序。
我想知道是否可以在具有智能指针的容器上调用 std::sort
并且仍然可以调用实际对象的比较运算符而不是指针 而无需 为'排序'提供第三个参数。
为了完整起见,MWE:
#include <vector>
#include <iostream>
#include <algorithm>
#include <memory>
class Date
{
public:
Date(int y, int m) : year(y), month(m) {}
bool operator<(const Date& rhs)
{
if (year > rhs.year) return false;
else if (year == rhs.year)
{
return month < rhs.month;
}
return true;
}
int year;
int month;
};
int main()
{
Date d1(1999,12);
Date d3(2000,10);
Date d2(2000,1);
Date d4(1997,9);
std::vector<std::shared_ptr<Date>> dates = {std::make_shared<Date>(d1), std::make_shared<Date>(d2), std::make_shared<Date>(d3), std::make_shared<Date>(d4)};
std::sort(dates.begin(), dates.end()); // doesn't work. orders by pointers
// std::sort(dates.begin(), dates.end(), [](std::shared_ptr<Date> d1, std::shared_ptr<Date> d2) { return *d1 < *d2; }); // this works
for (const auto& d : dates)
{
std::cout << d->year << " " << d->month << '\n';
}
return 0;
}
如您所见,std::shared_ptr
的比较运算符使用它所引用的指针。这样,比较相等的 2 个分配实例仍然比较不相等。
使用函数明确排序是一件好事。
std::sort(dates.begin(), dates.end(), [](std::shared_ptr<Date> d1, std::shared_ptr<Date> d2) { return *d1 < *d2; });
但是,如果您必须在多个地方执行此操作,您可以将 ptr 包装在 class/struct:
template<typename T>
struct SharedPtr final
{
std::shared_ptr<T> ptr;
bool operator==(const T &rhs) const
{ return *ptr == rhs; }
bool operator==(const SharedPtr<T> &rhs) const
{ return *ptr == *rhs.ptr; }
// ...
};
随意使用 nullptr 检查、其他重载和 operator<
进行扩展
对于您的情况,需要提供第三个参数。但是,如果您打算大量使用它,则可以通过创建一个重载 operator()
的特殊结构来简化它
class Date
{
public:
struct CompareSharedPtr
{
bool operator()(const std::shared_ptr<Date>& d1, const std::shared_ptr<Date>& d2)
{
return *d1 < *d2;
}
};
Date(int y, int m) : year(y), month(m) {}
bool operator<(const Date& rhs)
{
if (year > rhs.year) return false;
else if (year == rhs.year)
{
return month < rhs.month;
}
return true;
}
int year;
int month;
};
和用法
std::sort(dates.begin(), dates.end(), Date::CompareSharedPtr{});
我遇到的问题是,我有一个实现 operator<
.
shared_ptr
向量
在堆栈上使用 class 时,我可以使用 std::sort 而无需将 Compare
指定为排序参数。但是当然,当我使用 shared_ptr
时,它(显然我认为)会尝试对指针而不是对象本身进行排序。
我想知道是否可以在具有智能指针的容器上调用 std::sort
并且仍然可以调用实际对象的比较运算符而不是指针 而无需 为'排序'提供第三个参数。
为了完整起见,MWE:
#include <vector>
#include <iostream>
#include <algorithm>
#include <memory>
class Date
{
public:
Date(int y, int m) : year(y), month(m) {}
bool operator<(const Date& rhs)
{
if (year > rhs.year) return false;
else if (year == rhs.year)
{
return month < rhs.month;
}
return true;
}
int year;
int month;
};
int main()
{
Date d1(1999,12);
Date d3(2000,10);
Date d2(2000,1);
Date d4(1997,9);
std::vector<std::shared_ptr<Date>> dates = {std::make_shared<Date>(d1), std::make_shared<Date>(d2), std::make_shared<Date>(d3), std::make_shared<Date>(d4)};
std::sort(dates.begin(), dates.end()); // doesn't work. orders by pointers
// std::sort(dates.begin(), dates.end(), [](std::shared_ptr<Date> d1, std::shared_ptr<Date> d2) { return *d1 < *d2; }); // this works
for (const auto& d : dates)
{
std::cout << d->year << " " << d->month << '\n';
}
return 0;
}
如您所见,std::shared_ptr
的比较运算符使用它所引用的指针。这样,比较相等的 2 个分配实例仍然比较不相等。
使用函数明确排序是一件好事。
std::sort(dates.begin(), dates.end(), [](std::shared_ptr<Date> d1, std::shared_ptr<Date> d2) { return *d1 < *d2; });
但是,如果您必须在多个地方执行此操作,您可以将 ptr 包装在 class/struct:
template<typename T>
struct SharedPtr final
{
std::shared_ptr<T> ptr;
bool operator==(const T &rhs) const
{ return *ptr == rhs; }
bool operator==(const SharedPtr<T> &rhs) const
{ return *ptr == *rhs.ptr; }
// ...
};
随意使用 nullptr 检查、其他重载和 operator<
进行扩展对于您的情况,需要提供第三个参数。但是,如果您打算大量使用它,则可以通过创建一个重载 operator()
class Date
{
public:
struct CompareSharedPtr
{
bool operator()(const std::shared_ptr<Date>& d1, const std::shared_ptr<Date>& d2)
{
return *d1 < *d2;
}
};
Date(int y, int m) : year(y), month(m) {}
bool operator<(const Date& rhs)
{
if (year > rhs.year) return false;
else if (year == rhs.year)
{
return month < rhs.month;
}
return true;
}
int year;
int month;
};
和用法
std::sort(dates.begin(), dates.end(), Date::CompareSharedPtr{});