0

My question is slightly different from this one.

There is an unordered_set with TWO elements. I'd like to operate the two elements ''simultaneously'' like this:

unordered_set<vector<bool>> st;
st.insert(vector<bool>(100,true));
st.insert(vector<bool>(100,false));
// vector<bool> temp_v(100,true);
// temp_v[3] = false;
// st.insert(move(temp_v));
if (st.size()!=2) return;
for (int i=0; i<100; i++) 
  cout << (st.begin()->at(i)) ^ (st.rbegin()->at(i)) << endl;

However, unordered_set has no member function rbegin(). I know I can use an iterator pointing to u_s::begin() and advance it by one. Is there any more "elegant" way to do that?

-------------------------------------Solution------------------------------------------

Inspired by @YSC, an elegant way to achieve the purpose is:

auto & e1 = *begin(st);
auto & e2 = *(++begin(st));
for (int i=0; i<100; i++) cout << e1[i] ^ e2[i] << endl;

which, might rely on #include <algorithm>, is almost the same as the two-iterator solution.

user3813057
  • 891
  • 3
  • 13
  • 31
  • 7
    [`std::unordered_set`](http://en.cppreference.com/w/cpp/container/unordered_set) only provides forward iterators. There is no way to iterate backwards. Considering that an `unordered_set` is unordered, even the concept of a last element is dubious. There is a last element, but the fact that an element is the last shouldn't matter. – François Andrieux Feb 16 '18 at 16:21
  • 2
    Looks like you are using wrong container, which element is fist or second? – Slava Feb 16 '18 at 16:27
  • 4
    Just this `unordered_set> st;` doesn't compile. [__Life demonstration__](https://www.ideone.com/l8fcqS). For what could an unordered set of vectors be good anyway? What is your use case? This looks like an [XY Problem](http://xyproblem.info/) to me. – Jabberwocky Feb 16 '18 at 16:27
  • 3
    I fail to understand why you are trying to extract an order from an **UNORDERED** set. First? Last? Beginning? End? Those words are quite meaningless here. – Arnav Borborah Feb 16 '18 at 16:28
  • ...and what output do you expect for your code snippet? – Jabberwocky Feb 16 '18 at 16:35
  • There is no reverse iterator on unordered set because there is no difference between iterating forward or backward. It is completely unpredictable which element will be given first, and which element can be given second, so why bother? As a matter of fact, the order of iteration can change during the lifetime of the container. – SergeyA Feb 16 '18 at 16:40
  • @SergeyA: It's not *completely* unpredictable. For example, if you know the order beforehand and don't change the container, then the order must remain the same. It just depends on the hash function. I don't think the OP's requirement is completely unrealistic for all practical purposes, especially when you just maintain someone else's code and cannot completely rewrite it. – Christian Hackl Feb 16 '18 at 16:49
  • @ChristianHackl were you able to compile this? – Jabberwocky Feb 16 '18 at 16:50
  • @MichaelWalz: No. – Christian Hackl Feb 16 '18 at 16:51
  • @ChristianHackl "It's not completely unpredictable" sorry, if you write software that relies of not completely unpredictable behaviour please let people know in advance. – Slava Feb 16 '18 at 17:12
  • @Slava: So you believe if you take `begin` ten times in a row without changing the container in between, you may get ten different results? – Christian Hackl Feb 16 '18 at 17:23
  • @ChristianHackl no, I beleive I recompile program with different compiler or different optimization settings and behaviour of my program changes. It may be good for job security but... – Slava Feb 16 '18 at 17:59
  • @Slava: So if you don't recompile the program then it *is* predictable. There you go, that's all I intended to say. – Christian Hackl Feb 16 '18 at 18:05
  • @ChristianHackl "So if you don't recompile the program then it is predictable." no, thanks. btw what is the point of calculating this if container does not change? – Slava Feb 16 '18 at 18:11
  • @MichaelWalz Can you try `unordered_set > st` instead? I was trying to solve LeetCode Problem 782. My submitted code has `unordered_set > st` and the code is accepted. – user3813057 Feb 17 '18 at 16:48
  • @ArnavBorborah It does nor atter if there is an order. The only thing we need to know is that the TWO elements in the hash set are different. And we wish to refer to these two elements in one statement. – user3813057 Feb 17 '18 at 16:50
  • @Slava The hash set is used to restrict the number of distinct elements. There might be multiple, possibly duplicate, elements to be inserted into the hash set. But we only want to retain two distinct/unique elements. If the hash set grows to size 3 or above, we can assert the data set is undesirable. – user3813057 Feb 17 '18 at 16:54
  • @FrançoisAndrieux The order does not matter. The only thing we need to know is that the TWO elements in the hash set are different. And we wish to refer to these two elements in one statement. The code is modified. The operation in the `cout` statement is symmetric. So there is no "order". – user3813057 Feb 17 '18 at 16:55
  • If you only ever have two elements then why are you using a set in the first place? `vector a, b;` Done. – Lightness Races in Orbit Feb 17 '18 at 17:24

2 Answers2

0

Well, if you know for sure it has exactly two elements, KISS:

struct not_vector { /*...*/ };
unordered_set<not_vector> st;
// ...
not_vector const& first = *begin(st);
not_vector const& last  = *(++begin(st));

unordered_set iterators are ForwardIterator on which operator++ is defined and do what you expect. On the other hand, there is no way to go backward, only BidirectionalIterator can. This is why there is no unordered_set::rbegin().

YSC
  • 38,212
  • 9
  • 96
  • 149
  • 2
    I'm unable to compile even this: [__Life demonstration__](https://www.ideone.com/l8fcqS). – Jabberwocky Feb 16 '18 at 16:30
  • 1
    `std::next` would make the code even more elegant, i.e. `*(std::next(begin(st)))` – Christian Hackl Feb 16 '18 at 16:30
  • 3
    @ChristianHackl useless code cannot be more or less elegant – Slava Feb 16 '18 at 16:32
  • You would need to provide a specialization for `std::hash` or provide a custom hasher. If this code compiles, you are probably using some version of Visual Studio. – François Andrieux Feb 16 '18 at 16:32
  • You can't create an unordered set of a vector, since [it doesn't have a hash implemented for it](https://stackoverflow.com/a/29855973/6525260). You will have to make a specialization yourself. – Arnav Borborah Feb 16 '18 at 16:33
  • @Slava: Yes, I didn't try to compile the original code. – Christian Hackl Feb 16 '18 at 16:33
  • 2
    @ChristianHackl I am not about compliation, you can create proper hash, but whole concept of first and second element of unordered_set is meaningless. – Slava Feb 16 '18 at 16:35
  • @MichaelWalz: it was a "death demonstration" – Andriy Tylychko Feb 16 '18 at 16:41
  • @Slava: Not true for practical purposes, because there's the `begin` function and because you can iterate through the elements. – Christian Hackl Feb 16 '18 at 16:44
  • @MichaelWalz my answer doesn't show a full program: `unordered_set>` is used by OP as an example. They might be using another type, or an enhanced vector with a proper hash... I don't know, and this is not what is important here. – YSC Feb 17 '18 at 09:38
  • @Slava here, happy? – YSC Feb 17 '18 at 09:41
  • @MichaelWalz @FrancoisAndrieux . I'm sorry I did not know `vector` is not hashable. My original code is `unordered_set>`, and it compiles in the platform of the Life demonstration. – user3813057 Feb 17 '18 at 17:05
  • 1
    @user3813057 be careful with `vector` though, it is not a proper std container. – YSC Feb 17 '18 at 17:50
0

Is there any more "elegant" way to do that?

Yes this more obvious way to achieve pretty match the same:

int values[] { 0, 3 };
int index = random_number_generated_by_compiler_version() % 2;
std::cout << values[index] << values[!index] << std::endl;
Slava
  • 43,454
  • 1
  • 47
  • 90