15

Currently I'm creating a new set like this:

    std::set<A> s;
    s.insert(a1);
    s.insert(a2);
    s.insert(a3);
    ...
    s.insert(a10);

Is there a way to create s in one line?

Amir Rachum
  • 76,817
  • 74
  • 166
  • 248

6 Answers6

22
int myints[]= {10,20,30,40,50};
std::set<int> mySet(myints, myints + 5);

Ok, admittedly two lines :)

Moo-Juice
  • 38,257
  • 10
  • 78
  • 128
  • Nice, `+1` from me. That's even easier with [these](http://stackoverflow.com/questions/2552839/which-c-standard-library-wrapper-functions-do-you-use/2553081#2553081). – sbi Nov 16 '10 at 11:13
  • 1
    If it is available, then I prefer `... mySet(myints, myints+_countof(myints)) ...` – Martin Ba Nov 16 '10 at 11:21
  • 1
    Failing which, you can use `myints + sizeof(myints)/sizeof(int)`. – Stuart Golodetz Nov 16 '10 at 15:16
16

In C++0x the standard defines the Initializer List as an improvement for this kind of (awkward) construct.

It's much easier now:

std::set<int> set = {10, 20, 30, 40, 50};

All it took was for the standard library to declare the following constructor for set:

template <typename Value, typename Compare, typename Allocator>
set<Value, Compare, Allocator>::set(std::initializer_list<Value> list);

and all our worries were neatly swiped away.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • Note that nowadays, with C++11, you don't even need to declare that constructor. – Claudiu May 18 '15 at 19:25
  • @Claudiu: I don't quite understand what you mean, I am afraid. – Matthieu M. May 19 '15 at 06:14
  • I mean you can just do `std::set set = {10, 20, 30, 40, 50};` in your code without having to include `template set::set(std::initializer_list list);`. [Ideone example here](https://ideone.com/wlWCMl). – Claudiu May 19 '15 at 21:24
  • 2
    @Claudiu: Yes, the set constructor is provided by the set (not by the user), it is mentioned here for exposure only (to expose the feature being used). – Matthieu M. May 20 '15 at 06:35
  • Oh I understand now. I misread it the first few times around. Thanks. – Claudiu May 20 '15 at 13:43
  • @Claudiu: No worries, can you think of anything to make this answer clearer? If you misread, I would not be surprised if others did too. – Matthieu M. May 20 '15 at 14:28
  • 1
    Maybe rephrase it like "All it took was for the standard library to declare the following constructor for set:" ... "And all our worries were neatly swiped away." Past tense means it's already done, not something I have to do. And the rephrasing makes it impossible to misread "set" as "you" in the first sentence, which is what I did. – Claudiu May 20 '15 at 15:30
  • 1
    @Claudiu: Good idea! I edited your wording in. Thanks for helping me improve this answer. – Matthieu M. May 20 '15 at 16:33
9

You can look into Boost.Assign, which allows you to write things such as :

const std::list<int> primes = boost::assign::list_of(2)(3)(5)(7)(11);
icecrime
  • 74,451
  • 13
  • 99
  • 111
5

You might want to take a look at Boost.Assign:

http://www.boost.org/doc/libs/1_44_0/libs/assign/doc/index.html

Stuart Golodetz
  • 20,238
  • 4
  • 51
  • 80
5

If your initial data is in some container std::some_container<A> a; which has begin and end iterators, and this are forward iterators or best ones (they just should have operator++ overloaded) then you can make new set this way.

std::set<A> s(a.begin(), a.end());
Mihran Hovsepyan
  • 10,810
  • 14
  • 61
  • 111
4

Here's a C++0x alternative to Moo-Juice's answer for the case where construction of A is more expensive than for int.

int myints[]= {10,20,30,40,50};
size_t total(sizeof(myints) / sizeof(int));

auto begin(std::make_move_iterator(myints));
auto end(std::make_move_iterator(myints + total));

std::set<int> mySet(begin, end);
Steve Townsend
  • 53,498
  • 9
  • 91
  • 140