【发布时间】:2015-02-22 15:09:55
【问题描述】:
问题
我有一个自定义类型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;
}
假设我们想为struct A 保留原来的operator<(区分大小写),我们如何将std::pair<A, int> 与这种替代排序进行比较?
我知道为std::pair<A, int> 添加一个专门的operator< 版本可以解决问题:
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< 重新用于std::tuple 并将我的less-than 插入struct A 将是我想要的。可能吗?提前致谢!
【问题讨论】:
-
编写一个自定义比较函数来做你想做的事情相对简单。你真的想要
<语法吗? -
嗯,对于
std::pair<A, int>(或std::tuple<A, int, int>),函数不需要命名为operator<,可以使用其他名称,只要std::pair(或std::tuple) ) 可以用作std::map的键,使用接受比较函数作为参数的构造函数。但我不想(全部手动)为std::tuple<A, int, int>编写一个less-than函数,为std::tuple<int, A, int>编写另一个less-than函数等等。正如我在上面的问题中提到的那样,我想为std::pair(或std::tuple)重用默认的less-than。
标签: c++ c++11 operator-overloading std-pair stdtuple