0

I have many bool variables in struct Flags as:

struct Flags
{
    bool isATrue;
    bool isBTrue;
    bool isCTrue;
    ...
}

then in the other function I have calculate the bool result value of these Variables, now I have to put the variables which was true in the new Vector.e.g. if isBtrue == true. I have to put isBtruein the Vector TrueFlags. but C++ didn't support for() loop to iterate the struct. any one have some good idea?how to iterate struct in C++?

6
  • 1
    Hard to say what you need without more context but perhaps a std::map or some other container is what you want, rather than a struct? Commented Jan 13, 2021 at 8:32
  • 2
    sorry to say but you have two choices: 1) doing manually, 2) change the data structure Commented Jan 13, 2021 at 8:33
  • Take a look at the std::bitset. This might be what you are looking for Commented Jan 13, 2021 at 8:36
  • std::bitset does not provide begin and endstd::array<bool, N> might be an alternative, allowing range based for loop (losing advantage of compressed bools, gaining slightly faster access). In any case you might want to have an enum identifying the indices such that you can do e. g. allFlags[CFlag] to access what was formerly isCTrue. Commented Jan 13, 2021 at 8:50
  • Are you required to retain the struct as is for some reasons? Is changing the data structure an option at all? Commented Jan 13, 2021 at 9:13

5 Answers 5

2

You can use std::bitset and have:

// 3 stands for 3 flags you have in your struct
std::bitset<3> flags;

flags.set(0); // set bit at position 0 to true
flags.set(2); // set bit at position 2 to true

and then you can loop through it:

for (std::size_t i{ 0 }; i < flags.size(); ++i) {
    // access with flags[i]
}

You can also create an enum for direct flag access like:

enum Flags {
    IsATrue = 0,
    IsBTrue,
    IsCTrue
};

and then use it like: flags[IsATrue].

Sign up to request clarification or add additional context in comments.

1 Comment

Recommending yet to provide an enum for direct flag access (flags[IsATrue]), which likely should be retained (why members otherwise?).
0

If the number of values is fixed and known in advance, you can use array<bool>, otherwise use vector<bool>. Likewise for the is_true variable. Then you can easily loop over it.

Comments

0

One way is to use bitset as stated in other answer. But if structure Flags is something you have to use (from whatever reasons, for ex. maybe existing API, etc.), you can use operations wrapper and pointer to member to achieve "loop-ability". Something like (see Live):

struct Flags
{
    bool isATrue;
    bool isBTrue;
    bool isCTrue;
};

struct FlagsOp
{
    FlagsOp(Flags& f)
        : f{ f }
        , v({ &Flags::isATrue, &Flags::isBTrue, &Flags::isCTrue })
    {}
    size_t size() const { return v.size();}
    bool& operator[](size_t n) { return f.*(v[n]); }
private:
    Flags& f;
    vector<bool Flags::*> v;
};

int main()
{
    Flags f{};
    FlagsOp fop(f);

   fop[0] = true; // isATrue
   fop[1] = true; // isBTrue
   fop[2] = true; // isCTrue

    for (size_t i = 0; i < fop.size(); ++i)
        cout << fop[i] << '\n';
}

2 Comments

Instead of get/set I'd rather provide index operators. More C++ idiomatic... We might we working with std::ref in the data structure and the operator allowing modifications might return the raw reference then.
Fore completeness: bool operator[](size_t) const overload...
0

how to iterate struct in C++?

Same way as you would iterate anything that doesn't have a pre-existing standard iterator: By writing a custom iterator.

Writing custom iterators isn't simple, and writing this custom iterator is particularly complex due to lack of introspective language features, , . An incomplete, simplified example:

struct Flags
{
    bool isATrue;
    bool isBTrue;
    bool isCTrue;

    struct iterator {
        Flags* flags;
        int index;
        
        bool& operator*() {
            switch(index) {
                case 0: return flags->isATrue;
                case 1: return flags->isBTrue;
                case 2: return flags->isCTrue;
                default: throw std::out_of_range("You wrote a bug!");
            }
        }
        iterator& operator++() {
            index++;
            return *this;
        }
        iterator operator++(int) {
            iterator next = *this;
            index++;
            return next;
        }
        friend auto operator<=>(const iterator&, const iterator&) = default;
    };
    
    iterator begin() {
        return {this, 0};
    }
    iterator end() {
        return {this, 3};
    }
};

Note that although it is possible to iterate members of a class in C++, this is not necessarily efficient. It may be advisable to use an array instead of a class if you need efficient iteration.

Comments

0

If you do not want to change your struct Flags there is one other way. But first please read this And notice that this is not a portable solution. You can take advantage of unions by defining a union like this:

union Flagsunion{
    bool flag[sizeof(Flags)/ sizeof(bool)];
    Flags flags;
};

Assuming that the name of your std::vector<bool> is myvector and name of your Flags is myflags Then in your code:

    std::vector<bool> myvector;
    Flags myflags{ true, false, true};
    
    Flags2 my2ndflags;
    my2ndflags.flags = myflags;
    for(int i = 0; i < 3; ++ i){
        myvector.push_back(my2ndflags.flag[i]);
    }

7 Comments

Unfortunately type punning via unions is undefined behaviour in C++ (and there is no exception if only pure PODs are involved).
@Aconcagua thank you for the comment. Unfortunately I didn't completely understand it. could you please refer me to a source where I can read more about it? thanks in advance.
Might be of interest, too: stackoverflow.com/questions/25664848/unions-and-type-punning. Actually, some compilers do allow type punning as language extension. But then you rely on such compilers, thus at least you write non-portable code.
dear @Aconcagua I have already mentioned that. Please read the last part of my answer. Any way if you think This is bad answer, tell me to delete it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.