Initialize set based on field within array's class

Let's say I have code like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <numeric>
#include <algorithm>
#include <set>
#include <iterator>

enum Bar {
    A = 5,
    B = 7,
    C = 8,
    D = 9,
    Last
};

struct Foo {
    int bah;
    Bar bar;  
};

int main()
{
    Foo bar_arr[] = {
        { 0, A },
        { 0, B },
        { 0, B },
        { 0, C },
        { 0, B },
        { 0, B },
        { 0, C }
    };
    
    std::set<Bar> barset; //( ??? )
}


I want to initialize barset to be { A, B, C }, because that's what's within the bar_arr array.
I know I could just manually add to the set, but I was wondering if there was a nicer way of directly constructing it as such.

Edit:
1
2
    std::set<Bar> barset(std::begin(bar_arr), std::end(bar_arr),
        [](const Foo& lhs, const Foo& rhs) -> bool { return lhs.bar < rhs.bar; });
says the lambda can't be converted into
'const value_compare' (aka 'const std::less<Bar>')

It makes sense that this is an error, since I'm still missing something that's actually telling it to get a Bar out of a Foo.

Adding
1
2
3
    operator Bar() const {
        return bar;
    }
also doesn't resolve anything.
Last edited on
You mean like this?
 
std::set<Bar> barset { A, B, C };

If you want to collect the Bar values from bar_arr you could use an old-fashioned loop:
1
2
3
4
5
std::set<Bar> barset;
for (const Foo& foo : bar_arr)
{
	barset.insert(foo.bar);
}
Last edited on
Yes, I want it to be the equivalent of std::set<Bar> barset { A, B, C }.

Realistically, I'm going to end up going with a for loop like you have written, but was wondering if there was a way to initialize the barset object as { A, B, C }.
With the help of std::ranges::to, from C++23:
auto barset = transform_view(bar_arr, &Foo::bar) | to<set>();
Interesting, thanks I will note that for the future (current compiler for my project doesn't support it in the standard yet, but good to know).
C++20/23 ranges is almost like learning to program again! See:
https://en.cppreference.com/w/cpp/ranges

and also the ranges articles on
https://www.cppstories.com/

To paraphrase the chorus from a 'well known' song:


It's C++, but not as we know it, not as we know it, not as we know it;
it's C++, but not as we know it, not as we know it.


:) :)
C++20/23 ranges is almost like learning to program again!


https://www.cppstories.com/2023/four-views-in-cpp23/
With C++11 we could already say
std::transform(std::begin(bar_arr), std::end(bar_arr), std::inserter(barset, barset.end()), [](Foo f){return f.bar; });
Topic archived. No new replies allowed.