繁体   English   中英

如何在双精度数组上定义一个比较运算符(小于)?

[英]how to define a comparison operator (less than) on array of doubles?

我正在实现一个缓存来保存函数调用。

假设我的函数调用有2个double参数。

那些必须是一些LRU缓存的关键,或者 - 使其更简单 - 一个C ++ std::map

所以我创建了一个内部数组的模板类(可变数量的值)

template <int n>
  class DoubleArray
  {
    public:   
    double array[n];
   };

当尝试将其用作我的std::map一个键时,编译器抱怨,因为它需要一个operator<

.....\include\c++\7.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来回避这个问题。 使用别名声明可以将代码简化为

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;
}

如何创建通用比较运算符(可能使用模板递归)?

你可以试试这个方法:

#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。 它已经有一个重载的运算符<。 在编写自己的自定义解决方案之前,请始终考虑使用和组合标准库和其他知名库提供的内容: 尽可能使用库

然后,您可以像这样声明您的地图:

std::map<std::array<double, 2>, double> my_cache;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM