如何在双精度数组上定义比较运算符(小于)?
how to define a comparison operator (less than) on array of doubles?
我正在实施缓存以保存函数调用。
假设我的函数调用有 2 个 double
参数。
那些必须是某些 LRU 缓存的键,或者 - 为了更简单 - 一个 C++ std::map
。
所以我创建了一个模板class,其中包含数组(值的数量可变)
template <int n>
class DoubleArray
{
public:
double array[n];
};
当试图将它用作我的 std::map
的键时,编译器抱怨说它需要一个 operator<
。
.....\include\c++.3.1\bits\stl_function.h:386:20: note:
'const DoubleArray<2>' is not derived from 'const std::map<_Key, _Tp, _Compare,
_Alloc>'
{ return __x < __y; }
~~~~^~~~~
所以我实现了一个比较运算符(好吧,虽然我认为散列可以解决问题,但它似乎并非如此......)并编译:
#include <map>
template <int n>
class DoubleArray
{
public:
double array[n];
bool operator<(const DoubleArray &other) const
{
return (array[0] < other.array[0]) || (array[0] == other.array[0] && array[1] < other.array[1]);
}
};
int main()
{
std::map<DoubleArray<2>,double> my_cache;
DoubleArray<2> params;
// clumsy way to initialize the array...
params.array[0] = 12;
params.array[1] = 2;
// put a value in cache
my_cache[params] = 23;
}
请注意,比较运算符真的很笨拙。如果我有 6 个参数(这是我的真实情况)怎么办。
如何创建通用比较运算符(可能使用模板递归)?
如果这是一个 XY 问题,是否有更简单的方法来创建具有 double
类型的 n 值键映射?
(请注意,我完全知道使用 double
值作为键看起来很糟糕,但我的目标是在参数完全相同的函数调用上缓存值,这些不是为了存储等)
您正在寻找std::lexicographical_compare
bool operator<(const DoubleArray &other) const
{
return std::lexicographical_compare(array, array + n, other.array, other.array + n);
}
或者,您可以只为 std::array
定义一个别名,它已经定义了所有比较运算符
template<int n>
using DoubleArray = std::array<double, n>;
您可以使用 std::array
. Using an alias declaration 来回避问题,您的代码可以简化为
template <std::size_t N>
using DoubleArray = std::array<double, N>;
int main()
{
std::map<DoubleArray<2>,double> my_cache;
my_cache[{12, 2}] = 23;
}
How to create a generic comparison operator (maybe using template recursion) ?
你可以试试这个方法:
#include <utility> // std::index_sequence
#include <tuple> // std::tie
template <int N>
struct DoubleArray
{
private:
template <size_t ... Is>
bool opHelper(const DoubleArray& rhs, std::index_sequence<Is...>) const
{
return std::tie(arr[Is]...) < std::tie(rhs.arr[Is]...);
}
public:
double arr[N];
bool operator<(const DoubleArray& rhs) const
{
return opHelper(rhs, std::make_index_sequence<N>{});
}
};
不要重新发明轮子,用std::array。它已经有一个重载的运算符<。在编写您自己的自定义解决方案之前,请始终考虑使用和组合标准库和其他知名库提供的内容:Use libraries whenever possible.
然后您可以这样声明您的地图:
std::map<std::array<double, 2>, double> my_cache;
我正在实施缓存以保存函数调用。
假设我的函数调用有 2 个 double
参数。
那些必须是某些 LRU 缓存的键,或者 - 为了更简单 - 一个 C++ std::map
。
所以我创建了一个模板class,其中包含数组(值的数量可变)
template <int n>
class DoubleArray
{
public:
double array[n];
};
当试图将它用作我的 std::map
的键时,编译器抱怨说它需要一个 operator<
。
.....\include\c++.3.1\bits\stl_function.h:386:20: note:
'const DoubleArray<2>' is not derived from 'const std::map<_Key, _Tp, _Compare,
_Alloc>'
{ return __x < __y; }
~~~~^~~~~
所以我实现了一个比较运算符(好吧,虽然我认为散列可以解决问题,但它似乎并非如此......)并编译:
#include <map>
template <int n>
class DoubleArray
{
public:
double array[n];
bool operator<(const DoubleArray &other) const
{
return (array[0] < other.array[0]) || (array[0] == other.array[0] && array[1] < other.array[1]);
}
};
int main()
{
std::map<DoubleArray<2>,double> my_cache;
DoubleArray<2> params;
// clumsy way to initialize the array...
params.array[0] = 12;
params.array[1] = 2;
// put a value in cache
my_cache[params] = 23;
}
请注意,比较运算符真的很笨拙。如果我有 6 个参数(这是我的真实情况)怎么办。
如何创建通用比较运算符(可能使用模板递归)?
如果这是一个 XY 问题,是否有更简单的方法来创建具有 double
类型的 n 值键映射?
(请注意,我完全知道使用 double
值作为键看起来很糟糕,但我的目标是在参数完全相同的函数调用上缓存值,这些不是为了存储等)
您正在寻找std::lexicographical_compare
bool operator<(const DoubleArray &other) const
{
return std::lexicographical_compare(array, array + n, other.array, other.array + n);
}
或者,您可以只为 std::array
定义一个别名,它已经定义了所有比较运算符
template<int n>
using DoubleArray = std::array<double, n>;
您可以使用 std::array
. Using an alias declaration 来回避问题,您的代码可以简化为
template <std::size_t N>
using DoubleArray = std::array<double, N>;
int main()
{
std::map<DoubleArray<2>,double> my_cache;
my_cache[{12, 2}] = 23;
}
How to create a generic comparison operator (maybe using template recursion) ?
你可以试试这个方法:
#include <utility> // std::index_sequence
#include <tuple> // std::tie
template <int N>
struct DoubleArray
{
private:
template <size_t ... Is>
bool opHelper(const DoubleArray& rhs, std::index_sequence<Is...>) const
{
return std::tie(arr[Is]...) < std::tie(rhs.arr[Is]...);
}
public:
double arr[N];
bool operator<(const DoubleArray& rhs) const
{
return opHelper(rhs, std::make_index_sequence<N>{});
}
};
不要重新发明轮子,用std::array。它已经有一个重载的运算符<。在编写您自己的自定义解决方案之前,请始终考虑使用和组合标准库和其他知名库提供的内容:Use libraries whenever possible.
然后您可以这样声明您的地图:
std::map<std::array<double, 2>, double> my_cache;