2

I was trying to find out the union of two set containing strings, using set_union(...) function. But, it's throwing error inside of stl_algo.h ar line no 4948 -

Error : passing 'const std::__cxx11::basic_string<char>' as 'this' argument discards qualifiers [-fpermissive]

My code :

#include<bits/stdc++.h>

using namespace std;

int main()
{
    int t,k, tmp, i=1,j,l,m,n,x1,x2;
    cin>>n;
    string st,stt;
    set <string> set1,set2,set3;
    set1.insert("sdsd");
    set1.insert("sdswewd");
    set1.insert("ssd");

    set2.insert("sdsd");
    set2.insert("sdfewew");
    set2.insert("ssd");
    set_union(set1.begin(),set1.end(),set2.begin(),set2.end(),set3.begin());

    return 0;
}

fardinabir
  • 116
  • 8
  • 3
    Possible duplicate of [Union Operation For std::set](https://stackoverflow.com/questions/23437015/union-operation-for-stdset) – Blaze Sep 25 '19 at 08:23
  • 4
    Also please read [Why should I not #include ?](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) and [Why is “using namespace std;” considered bad practice?](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) – Blaze Sep 25 '19 at 08:24
  • Unwanted initializations could also be removed in the above example. (int and string initialized but not used ) – Kiran Thilak Sep 25 '19 at 08:37

2 Answers2

3

try using std::inserter

set_union( set1.begin(), set1.end(), set2.begin(), set2.end(),std::inserter( set3, set3.begin() ));

Update:

a1.begin() is simply not an output iterator. inserter(a1,a1.begin()) returns an output iterator which will invoke the set's insert function for each element... Why do we need an inserter function call when doing a set_union for a set?

Also since we are dealing with std::set a container where uniqueness is guaranteed we don't need to take a set_union because a simple set insert will also ensure it that no copies of same element is created.

//insert all element of set 1 to set 3
set3.insert(set1.begin(),set1.end());
//insert all elements of set 2 (that is not in set 1) to set 3
set3.insert(set2.begin(),set2.end());
Kiran Thilak
  • 443
  • 4
  • 15
  • 1
    This answer is correct, but you should explain what the problem in the original code is, and why this fixes it. – Pete Becker Sep 25 '19 at 13:07
0

As mentioned in another answer, std::inserter would do the job. Alternatively, you can store the output from the set_union in a vector and if necessary, construct another set using the values from the output vector.

However, it should be noted that this approach requires that you know the size of the vector either at run-time (set by the user) or at compile time. In the latter case, you can use an std::array. If the output is not known (i.e. calculated) then the output vector might to be large enough to store the results and you're program will crash (memory leak).

#include<iostream>
#include<set>
#include<string>
#include<algorithm>
#include<vector>

int main()
{
    std::set<std::string> set1,set2;
    set1.insert("sdsd");
    set1.insert("sdswewd");
    set1.insert("ssd");

    set2.insert("sdsd");
    set2.insert("sdfewew");
    set2.insert("ssd");

    std::vector<std::string> output(4);
    std::set_union(set1.begin(),set1.end(),set2.begin(),set2.end(),output.begin());

    std::set<std::string> set3(output.begin(),output.end());
}

Online example: https://rextester.com/MUPHB45816

There is also a code example here which uses vectors.

Constantinos Glynos
  • 2,584
  • 1
  • 11
  • 27
  • 2
    I highly discourage the presized output vector with its begin() iterator as output. You are better off with just a back_inserter. Otherwise bad things will happen for other outputs – phön Sep 25 '19 at 08:43
  • @phön: Yep. I agree that `inserter` or `back_inserter` are better options. I just posted the answer as an alternative option. Besides, you can resize the `std::vector` to fit the `std::set` contents if needed. – Constantinos Glynos Sep 25 '19 at 08:45
  • 2
    How could i resize std::vector to fit the set? which set. You dont know the size in advance. std::set_union will just happyly insert at the iterator assuming your vector is already big enough. If you input less values you have a vector with default constructed strings. if you input more you have undefined behaviour (out of bounds). This solution is asking for trouble and this has nothing to do with the usage of vector per se. Just your usage of the vector is bad. – phön Sep 25 '19 at 08:59
  • @phön: An example of resizing the vector to the set bounds is shown in the code example that uses vectors. Once again, I agree that this approach is not as elegant as the `inserter` solution when the size of the output is unknown. However, this is an alternative approach and has it's usages. For example, if you know the number of elements at run-time, then using a `vector` is far faster than using a `set`. If you know the number of elements at compile time, then an `array` is even better. You don't have to get wound up. This is programming. There are more than one solutions to a problem. – Constantinos Glynos Sep 25 '19 at 09:53
  • As said i am not questioning the vector vs set. I am questioning the usage. for example I only need to change one "ssd" to "ssdxxx" and the whole snippet is crashing. You either have to set the preset size to the sum of both set sizes and resize later (as you described) or just use back_inserter and be happy. Some newcomer is going to copy this snippet. Maybe even OP. And this will lead to trouble later on. – phön Sep 25 '19 at 10:20
  • 1
    @phön: Yes, indeed. If you change the input to what you suggest, then the output `vector` is not going to be large enough and it'll crash. No doubt or argument there. This is why I said that if you know the size at run-time (i.e. set by the user) or compile time, then using a `vector` or an `array` would be better matches to `inserter` algorithms. In any other circumstance, you are correct that it will cause problems. But I didn't make it clear in my answer and it didn't really occur to me that someone might blindfoldedly copy this code. Thanks, I will ammend. – Constantinos Glynos Sep 25 '19 at 10:26
  • Good to see we are on the same page now :-P – phön Sep 25 '19 at 10:30
  • @phön: Absolutely! I think we were on the same page from the beginning, but we may have lost it in the communication. haha. :-) – Constantinos Glynos Sep 25 '19 at 10:31