3

I have say the following bool vector

v = [false ,true, false ,false ,true, false ,false ,true]

I want another vector which contains the indices of v for which the elements are true.

I have the following code:

std::vector<int> nds; //contains the indices
for (const auto &elem : v)
{
    auto idx = &elem - &v[0];
    if (elem)
    {
        nds.push_back(idx);
    }
}

The above seems to work on my MacBook but it is causing the following error on Linux.

src/file.cpp:76:25: error: taking address of temporary [-fpermissive]
                         auto idx = &elem - &v[0];
                                                ^

Is there a better way to find the indices?

P.S. This is just a snippet of some larger code.

Morpheus
  • 3,285
  • 4
  • 27
  • 57
  • 1
    Closely related https://stackoverflow.com/questions/8399417/why-vectorboolreference-doesnt-return-reference-to-bool – StoryTeller - Unslander Monica Jul 01 '20 at 09:45
  • 1
    And on the whole, I recommend reading this https://stackoverflow.com/questions/670308/alternative-to-vectorbool – StoryTeller - Unslander Monica Jul 01 '20 at 09:46
  • If you want the indices, loop over the indices. The range loop is useful when you don't care about what they are. – molbdnilo Jul 01 '20 at 09:48
  • the storage for a boolean in a vector of bools is (often) just a bit, which is not addressable, so it (may) return a proxy to it (not the actual storage), which is a temporary object. I recommend just not using vector ever - even if all you do is wrap a bool in a struct and make a vector – xaxxon Jun 07 '21 at 20:36

2 Answers2

8

is there a better way to find the indices?

Use a classical for loop

for (int i = 0; i != v.size(); ++i) {
  if (v[i]) nds.push_back(i);
}
Andreas DM
  • 10,685
  • 6
  • 35
  • 62
4

Using the range-v3 library, you can use a functional programming style approach to chain the lazy views::enumerate iterator with the lazy views::filter and views::transform view transformations to construct an std::vector<int> of the true-valued (original) indices:

const auto nds = v | views::enumerate 
   | views::filter([](auto p) { return p.second; }) 
   | views::transform([](auto p) { return p.first; }) 
   | to<std::vector<int>>;

DEMO.


Alternatively, replacing the views::transform with views::keys:

const auto nds = v | views::enumerate 
    | views::filter([](auto p){ return p.second; })
    | views::keys
    | to<std::vector<int>>;

DEMO.

dfrib
  • 70,367
  • 12
  • 127
  • 192