Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用自定义std::set比较器_C++_Stl - Fatal编程技术网

C++ 使用自定义std::set比较器

C++ 使用自定义std::set比较器,c++,stl,C++,Stl,我试图将一组整数中的项的默认顺序改为字典顺序而不是数字顺序,但我无法使用g++编译以下内容: file.cpp: bool lex_compare(const int64_t &a, const int64_t &b) { stringstream s1,s2; s1 << a; s2 << b; return s1.str() < s2.str(); } void foo() { set<int64

我试图将一组整数中的项的默认顺序改为字典顺序而不是数字顺序,但我无法使用g++编译以下内容:

file.cpp:

bool lex_compare(const int64_t &a, const int64_t &b) 
{
    stringstream s1,s2;
    s1 << a;
    s2 << b;
    return s1.str() < s2.str();
}

void foo()
{
    set<int64_t, lex_compare> s;
    s.insert(1);
    ...
}
bool-lex\u-compare(常量int64\u t&a,常量int64\u t&b)
{
流s1、s2;

s1您使用的是一个函数,其中应该使用一个函子(一个重载()运算符的类,以便可以像函数一样调用它)


Yacoby的回答启发我编写了一个用于封装functor样板的适配器

template< class T, bool (*comp)( T const &, T const & ) >
class set_funcomp {
    struct ftor {
        bool operator()( T const &l, T const &r )
            { return comp( l, r ); }
    };
public:
    typedef std::set< T, ftor > t;
};

// usage

bool my_comparison( foo const &l, foo const &r );
set_funcomp< foo, my_comparison >::t boo; // just the way you want it!
模板
类集合函数{
结构ftor{
布尔运算符()(T常量和l,T常量和r)
{返回comp(l,r);}
};
公众:
typedef std::setT;
};
//用法
bool my_比较(foo const&l、foo const&r);
设置funcomp::t boo;//正是您想要的方式!

哇,我认为这是值得的!

您可以使用函数比较器,而不必像这样包装它:

bool comparator(const MyType &lhs, const MyType &rhs)
{
    return [...];
}

std::set<MyType, bool(*)(const MyType&, const MyType&)> mySet(&comparator);
bool比较器(常量MyType&lhs、常量MyType&rhs)
{
返回[…];
}
std::设置mySet(&comparator);
每当您需要一组该类型的数据时,键入这些数据都会让人恼火,如果您不使用相同的比较器创建所有数据集,则可能会导致问题。

1.现代C++20解决方案 然后使用它,无论是这样:

std::set<int, decltype(cmp)*> s(cmp);
std::set<int, decltype(&cmp)> s(&cmp);

5.替代解决方案:从布尔函数创建结构 取布尔函数

bool cmp(int a, int b) {
    return ...;
}
bool cmp(int a, int b) {
    return ...;
}
并使用

#包括
使用Cmp=std::积分常数;
最后,使用结构作为比较器

std::set<X, Cmp> set;
std::set;

std::less
在使用
operator@Omry我很想知道你用的是什么编译器:@你使用的是哪种编译器?@ McRy C++标准说第二个模板参数必须是一个类型的名称。函数名不是一个类型的名称。我们可以使用DECKET吗?(lex_compare)表示函数类型?@LewisChan正确的术语是
std::set s(&lex_compare)<代码> >我想,哇!确实是!但是它也指出了C++语法是多么可怕。我希望将来的版本和标准可以简化C++语法。@ Nav.<代码>::t//>部分可以在C++ 14中被消除。我认为它看起来和java泛型等价物一样好,同时保证了零运行时开销。在例子1中,CMP NEE。d将被传递到构造函数中?集本身是否会构造一个,因为lambda类型是作为模板类型给出的?@PeteUK,在C++20之前,必须将比较器传递到构造函数中。在C++20中,可以使用不带参数的构造函数。谢谢您的提问;答案是updated@diralik非常感谢您对a的回复和更新L答案已经很好了。这5.太疯狂了。人们每天都会发现这种语言的新的角落和缝隙。升级到公认的答案(在最初的问题被问到10多年后!)。我认为是时候编辑你的用户名了@嗨,你的意思是什么?西罗,再也没有禁令了。一个不应该被点名的人已经离开了办公室,应该像人们忘记愚蠢一样被遗忘jokes@A_P只要特朗普仍然被禁止使用推特,质疑它是有道理的。
auto cmp = [](int a, int b) { return ... };
std::set<int, decltype(cmp)> s(cmp);
bool cmp(int a, int b) {
    return ...;
}
std::set<int, decltype(cmp)*> s(cmp);
std::set<int, decltype(&cmp)> s(&cmp);
struct cmp {
    bool operator() (int a, int b) const {
        return ...
    }
};

// ...
// later
std::set<int, cmp> s;
bool cmp(int a, int b) {
    return ...;
}
#include <type_traits>
using Cmp = std::integral_constant<decltype(&cmp), &cmp>;
std::set<X, Cmp> set;
template< class K > iterator find( const K& x );
template< class K > const_iterator find( const K& x ) const;
#include <cassert>
#include <set>

class Point {
    public:
        // Note that there is _no_ conversion constructor,
        // everything is done at the template level without
        // intermediate object creation.
        //Point(int x) : x(x) {}
        Point(int x, int y) : x(x), y(y) {}
        int x;
        int y;
};
bool operator<(const Point& c, int x) { return c.x < x; }
bool operator<(int x, const Point& c) { return x < c.x; }
bool operator<(const Point& c, const Point& d) {
    return c.x < d;
}

int main() {
    std::set<Point, std::less<>> s;
    s.insert(Point(1, -1));
    s.insert(Point(2, -2));
    s.insert(Point(0,  0));
    s.insert(Point(3, -3));
    assert(s.find(0)->y ==  0);
    assert(s.find(1)->y == -1);
    assert(s.find(2)->y == -2);
    assert(s.find(3)->y == -3);
    // Ignore 1234, find 1.
    assert(s.find(Point(1, 1234))->y == -1);
}
g++ -std=c++14 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out