【问题标题】:Using functors without default constructors for stl containers为 stl 容器使用没有默认构造函数的函子
【发布时间】:2014-08-22 10:16:27
【问题描述】:

我想为std::set 使用我自己的比较器,它需要将参数传递给它的构造函数:

template <class T = double> class EpsCompare {
  public:
    EpsCompare(T input_eps) : _eps(input_eps) {};
    bool operator() (const T & element1, const T & element2) const {
       return ( round(element1*_eps) < round(element2*_eps) );
    }
    T _eps;
};

如何将它传递给我的设置数据类型的声明?我想做这样的事情:

std::set<double, EpsCompare<double>(1e-5)> myEpsSet;

这不编译,那还能怎么办呢?

【问题讨论】:

  • 将实例传递给构造函数:en.cppreference.com/w/cpp/container/set/set
  • 被这个比较器烧死。绝不。曾经。曾经。采用。一个。厄普西隆。什么时候。排序。数字。永远。
  • @n.m.为什么?而且我什至不认为这是典型意义上的 epsilon。
  • @Angew 你说得对,这不是通常的模糊比较,我的眼睛看到他们想要什么,而不是写什么:(至于为什么,模糊比较不是严格的弱排序,所以通常的算法是行不通的。想象一下一个数字序列,每个数字都在下一个 epsilon 之内,但极端情况还很遥远;你会如何对它们进行排序?
  • 第二个要设置的模板参数应该是一个合适的类,这里是一个类的实例(但不是一个类本身)

标签: c++ stl argument-passing functor default-constructor


【解决方案1】:
std::set<double, EpsCompare<> > myEpsSet(EpsCompare<>(1e-5));

std::set<double, EpsCompare<double> > myEpsSet(EpsCompare<double>(1e-5));

【讨论】:

  • 是否有任何理由将EpsCompare&lt;double&gt; 作为第二个参数传递给std::set 模板?
  • @Slava,是的,这是必需的。与函数模板不同,模板参数不是从用于构造类模板实例的参数推导出来的。
  • 我不关注。需要什么?如果不传给template,只传给std::setctor,会有什么不同?
  • @Slava std::set 的第二个模板参数设置比较器的类型。默认情况下,它是std::less&lt;T&gt;(其中T 是第一个模板参数)。但是你不想使用std::less&lt;double&gt; 类型的对象,你需要EpsCompare&lt;double&gt; 类型的对象。
  • 我的问题实际上有点复杂,因为我没有尝试直接调用myEpsSet,而是在类声明中。但随后在新类构造函数的初始化程序中使用相同的方法完成了这项工作:class Testclass { public: std::set&lt;double, EpsCompare&lt;double&gt; &gt; myEpsSet; Testclass() : myEpsSet(EpsCompare&lt;double&gt;(1e-5)) {}; }
【解决方案2】:

某事

#include <iostream>
#include <set>

template <class T = double> class EpsCompare {
  public:
    EpsCompare(T input_eps) : _eps(input_eps) {};
    bool operator() (const T & element1, const T & element2) const {
       return ( round(element1*_eps) < round(element2*_eps) );
    }
    T _eps;
};


int main() 
{
    std::set<double, EpsCompare<double>> myEpsSet(EpsCompare<double>(1e-5) );

    return 0;
}

【讨论】:

    【解决方案3】:

    如果您想将eps 作为参数传递给std::set,您必须使其成为模板的一部分。您不能使用double 作为模板参数,因此具有作为模板参数的权力的解决方案之一:

    template <class T, int power > class EpsCompare {
      public:
        EpsCompare() { eps = pow( 10, power ); }
        bool operator() (const T & element1, const T & element2) const {
           return ( round(element1*eps) < round(element2*eps) );
        }
      private:
           T eps;
    };
    
    std::set<double, EpsCompare<double,-5>> myEpsSet;
    

    如果您想将 eps 作为参数传递给 EpsCompare 构造函数,请将其设为运行时,因此您不能在模板中使用它并将比较器传递给 std::set

    std::set<double,EpsCompare<double>> myEpsSet( EpsCompare<double>( 1e-5 ) );
    

    足够了。

    【讨论】:

    • 我之前曾尝试过类似的解决方案,但考虑到我真正想要传递的是一个区间大小(可能是 1.5 或其他值),而不总是只是数量数字...
    • 那么你必须在运行时传递它,除非你找到一种方法将它指定为多个整数。
    猜你喜欢
    • 1970-01-01
    • 2023-03-20
    • 2016-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-11
    相关资源
    最近更新 更多