问题
我有一个自定义类型A
,它具有自然排序(有operator<
)和多个替代排序(区分大小写、不区分大小写等)。现在我有一个std::pair
(或std::tuple
)由(一个或多个)组成A
。以下是一些我想比较的类型示例:std::pair<A, int>
, std::pair<int, A>
, std::tuple<A, int, int>
, std::tuple<int, A, int>
. 我如何使用默认的逐元素比较实现来比较std::pair
(或),插入我的比较函数?std::tuple
A
编码
下面的代码无法编译:
#include <utility> // std::pair
#include <tuple> // std::tuple
#include <iostream> // std::cout, std::endl
struct A
{
A(char v) : value(v) {}
char value;
};
// LOCATION-1 (explained in the text below)
int main()
{
std::cout
<< "Testing std::pair of primitive types: "
<< (std::pair<char, int>('A', 1)
<
std::pair<char, int>('a', 0))
<< std::endl;
std::cout
<< "Testing std::tuple of primitive types: "
<< (std::tuple<char, int, double>('A', 1, 1.0)
<
std::tuple<char, int, double>('a', 0, 0.0))
<< std::endl;
// This doesn't compile:
std::cout
<< "Testing std::pair of custom types: "
<< (std::pair<A, int>('A', 1)
<
std::pair<A, int>('a', 0))
<< std::endl;
return 0;
}
这是因为operator<
没有为struct A
. 将其添加到LOCATION-1
上面将解决问题:
bool operator<(A const& lhs, A const& rhs)
{
return lhs.value < rhs.value;
}
现在,我们有另一种排序方式struct A
:
bool case_insensitive_less_than(A const& lhs, A const& rhs)
{
char const lhs_value_case_insensitive
= ('a' <= lhs.value && lhs.value <= 'z'
? (lhs.value + 0x20)
: lhs.value);
char const rhs_value_case_insensitive
= ('a' <= rhs.value && rhs.value <= 'z'
? (rhs.value + 0x20)
: rhs.value);
return lhs_value_case_insensitive < rhs_value_case_insensitive;
}
假设我们想保留原来operator<
的 for struct A
(区分大小写的),我们如何std::pair<A, int>
与这种替代排序进行比较?
我知道添加operator<
for的专用版本可以std::pair<A, int>
解决问题:
bool operator<(std::pair<A, int> const& lhs, std::pair<A, int> const& rhs)
{
return (case_insensitive_less_than(lhs.first, rhs.first)
? true
: case_insensitive_less_than(rhs.first, lhs.first)
? false
: (lhs.second < rhs.second));
}
但是,我认为这是一个次优的解决方案。
首先,对于std::pair
,重新实现逐元素比较很容易,但std::tuple
它可能很复杂(处理可变参数模板)并且容易出错。
其次,我几乎无法相信这是解决问题的最佳实践方法:想象我们必须为operator<
以下每个类定义一个专门的版本:std::tuple<A, int, int>
, std::tuple<int, A, int>
, std::tuple<int, int, A>
, std::tuple<A, A, int>
, ... (这甚至不是一种实用的方法!)
重新使用编写良好的内置operator<
forstd::tuple
并插入我less-than
的 forstruct A
将是我想要的。可能吗?提前致谢!