代码之家  ›  专栏  ›  技术社区  ›  Jean-François Fabre

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

  •  4
  • Jean-François Fabre  · 技术社区  · 6 年前

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

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

    这些必须是一些LRU缓存的关键,或者使它更简单——一个C++ std::map .

    所以我创建了一个包含数组的模板类(变量值数)

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

    当试图用它作为我的钥匙 STD::地图 ,编译器抱怨,因为它需要 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问题,有没有更简单的方法来创建一个n值的键映射 双重的 类型?

    (请注意,我完全知道使用 双重的 作为键的值看起来不好,但我的目标是在参数完全相同、不打算存储的函数调用上缓存值或类似的值)

    4 回复  |  直到 6 年前
        1
  •  4
  •   NathanOliver    6 年前

    您可以使用 std::array . 使用一个 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;
    }
    
        2
  •  8
  •   Caleth    6 年前

    你在找 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>;
    
        3
  •  2
  •   Julien Villemure-Fréchette    6 年前

    不要重新发明轮子,使用std::array。它已经有一个过载的操作员<。在编写自己的自定义解决方案之前,请始终考虑使用和组合标准库和其他知名库提供的功能: Use libraries whenever possible .

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

    std::map<std::array<double, 2>, double> my_cache;
    
        4
  •  2
  •   K. Kiryu    6 年前

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

    您可以尝试以下方法:

    #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>{});
        }
    };