C++ 在C++;

C++ 在C++;,c++,stl,C++,Stl,我想反转std::set的内容(不只是反向迭代,而是反转iteslf的内容)。我发现std::set将compare作为其构造函数的函数对象。因此,我提出了以下代码来执行相同的操作: #include <set> using namespace std; struct Comparator { Comparator(bool g) : m_g(g){} bool operator()(int i1, int i2) const { if(m_

我想反转
std::set
的内容(不只是反向迭代,而是反转iteslf的内容)。我发现
std::set
将compare作为其构造函数的函数对象。因此,我提出了以下代码来执行相同的操作:

#include <set>
using namespace std;
struct Comparator
{
    Comparator(bool g) : m_g(g){}
     bool operator()(int i1, int i2) const
    {
        if(m_g)
        {
            return i1>i2;
        }
        return i1<i2;
    }
        bool m_g;
};

int main(int argc, char** argv)
{
    Comparator l(false);
    set<int,Comparator> a(l);
    a.insert(1);
    a.insert(2);
    a.insert(3);
    Comparator g(true);
    set<int,Comparator> b(g);
    copy(a.begin(), a.end(), inserter(b, b.begin()));
    a = b;
    return 0;
}
#包括
使用名称空间std;
结构比较器
{
比较器(bool g):m_g(g){}
布尔运算符()(int i1,int i2)常量
{
if(m_g)
{
返回i1>i2;
}

返回I1

是的,这是合法的。考虑如果比较器不允许有状态,就没有必要允许比较器作为构造器参数。


只要比较器提供严格的弱排序,就可以了(除其他外,这意味着它必须是一致的。您不能中途更改它的状态,以便它对元素进行不同的排序)

您的代码没有问题


比较器有状态也没有错。

你不需要提供一个维护状态的函数对象。只要使用一个正常的函数,它就可以完成这项工作。请不要介意使用lambda。作为打印的捷径

typedef bool (*Cmp)(int x, int y);

bool Compare(int x, int y)
{
    return x < y;
}


bool CompareR(int x , int y)
{
    return !Compare(x, y);
}

 void SetReverse()
{

    std::set<int, Cmp> s1(Compare);

    s1.insert(1);
    s1.insert(3);
    s1.insert(2);
    s1.insert(4);

    std::for_each(s1.begin(), s1.end(), [](int x) { std::cout << x << "\n"; });

    std::set<int, Cmp> s2(CompareR);

    s2.insert(s1.begin(), s1.end());
    std::for_each(s2.begin(), s2.end(), [](int x) { std::cout << x << "\n"; });

          s1 = s2;

}
typedef bool(*Cmp)(整数x,整数y);
布尔比较(整数x,整数y)
{
返回xstd::for_each(s1.begin()、s1.end()、[](int x){std::cout如果你有一个足够大的集合,你已经支付了O(NlogN)罚款来创建一个平衡的二叉树。如果盲插入目标集合,你将不得不再次支付罚款

考虑使用这些插入重载之一

 void insert ( InputIterator first, InputIterator last );
 iterator insert ( iterator position, const value_type& x );

如果[first,last]已排序,则范围插入具有线性复杂性。

这很好,但它不必要地复杂


您可以使用标准库中的
std::less
(该模板参数的默认值!)或
std::greater
。它们由

提供,这是可以的,因为您的比较不会动态更改,并且它提供严格的弱排序

但是,如果这样做的话,即使顺序发生变化,集合的类型也是相同的,我可能会建议另一种方法。与其进行比较,不如使用两种不同的集合类型,分别使用
std::less
std::greater
,并像标准库一样使用迭代器接口,而不是容器接口这取决于所有模板参数

最后,正如@parapura rajkumar的回答所指出的,您应该使用迭代器对构造函数,而不是
std::copy

// Assuming my other comments don't apply, modify as needed if they do:
Comparator g(true);
set<int, Comparator> b(a.rbegin(), a.rend(), g);
//假设我的其他注释不适用,如果适用,请根据需要进行修改:
比较器g(真);
集合b(a.rbegin(),a.rend(),g);

更通用的解决方案。boost::assign和c++11只是为了方便(和有趣的自动反转)

#包括
#包括
#包括
使用名称空间boost::assign;
模板
结构revPred{
revPred(Pred-Pred):Pred(Pred){}
布尔运算符()(常数CL&a、常数CL&b)
{
返回pred_(b,a);
}
Pred Pred_;
};
模板
内联
标准::设置反向设置(常量标准::设置和设置){
设置资源(revPred(set.key_comp());
std::copy(set.begin(),set.end(),std::inserter(res,res.begin());
返回res;
}
int main()
{
std::集s;s+=0,1,2,3;

std::for_each(s.begin()、s.end()、[](int x){std::如果不更改状态中间比较,我看不出为什么不可以。您应该将bool设置为私有以保护这一点,如果您担心样式,那么首先可能使用类而不是结构-比较器对我来说更像是类而不是结构。通常,您会使用不同的比较器类型。这重要吗对于在这两种情况下集合具有相同类型的用例?在比较器上模板化排序顺序会稍微快一些,因为编译器在编译时知道布尔常量,在运行时实际上跳过一个分支。@Jalf:是的,我需要使用相同的对象。我的所有其他代码都访问此集合,所以我不能使用不同的比较器r类型。我很好奇你到底需要如何使用它。我很难想出一种情况,我不能只使用相同的精确集,而只能修改我的算法以适应所需的顺序。人们喜欢使用函数对象而不是函数的原因是性能更好——你不能内联间接调用。jagansai,我很瘦k您的答案是错误的,因为!compare将给出x>=y,这不是弱严格排序。这就是为什么您无法访问集合本身使用的比较器。(您可以使用
std::set::key_comp()
获得它的副本,但它会按值返回,因此您只能获得一个副本。)但是,类型将不相同,即第一个类型将是
std::set
,第二个类型将是
std::set
。我希望类型相同。“我希望类型相同”用于什么目的?您将比较器存储在一个容器中?o_o
    # include <iostream>
# include <set>
# include <boost/assign.hpp>


using namespace boost::assign;

template <typename CL , typename Pred>
struct revPred {
    revPred (Pred pred) : pred_(pred) {}
bool operator()(const CL & a, const CL& b)
{
 return pred_(b,a);
 }
Pred pred_;
};

template <typename CL , typename Pred, typename alloc>
inline
std::set<CL,revPred<CL,Pred>,alloc> reverseSet(const std::set<CL,Pred,alloc> & set) {
    std::set<CL,revPred<CL,Pred>,alloc> res(revPred<CL,Pred>(set.key_comp()));
    std::copy(set.begin(), set.end(), std::inserter(res, res.begin())); 
    return res;
    }

int main()
{
 std::set<int> s; s += 0 , 1 , 2 , 3;
 std::for_each(s.begin(), s.end(), [](int x) { std::cout << x << " "; }); 
 std::cout << std::endl;
 auto reverse = reverseSet(s);
 std::for_each(reverse.begin(), reverse.end(), [](int x) { std::cout << x << " "; }); 
 std::cout << std::endl;
 return 0; 
}