-3

I am trying to convert struct with boolean value into an another variable of boolean type. I am trying using static_cast and reinterpet_cast.

int main()
{
    bool c,d;

    struct b {
        bool b1 = false; 
        bool b2 = false;
    };

    c = reinterpret_cast<uint8_t*>(&b);
    d = (static_cast<uint8_t*>(static_cast<void*>(&b)));
    cout <<c <<endl;
    cout <<d <<endl;

    return 0;
}

The error is:

main.cpp:22:38: error: expected primary-expression before ')' token
     c = reinterpret_cast<uint8_t*>(&b);
                                      ^
main.cpp:23:53: error: expected primary-expression before ')' token
     d = (static_cast<uint8_t*>(static_cast<void*>(&b)));
underscore_d
  • 6,309
  • 3
  • 38
  • 64
  • 1
    You forgot to ask any question. But why do you think those errors are wrong, i.e. why do you think you can do those conversions? They don't look like sensible conversions. Even if the syntax was fixed, `uint8_t` isn't guaranteed to be any `char` type, so it's not guaranteed that that cast will satisfy the aliasing rules. Besides, it's *less* clear why you feel the need to do such casts in the first place. I'm voting to flag this as unclear what you're asking, as you didn't explain *why* you're doing this, just *how* you're currently attempting, and that is unclear in itself. – underscore_d Apr 17 '18 at 14:16
  • 3
    You don't have a `struct b` to convert to a bool. But it doesn't make sense to convert a struct to a bool, anyway. I see your struct contains two bools -- are you trying to extract one, or the other, or perform a Boolean operation on the two? – Steve Summit Apr 17 '18 at 14:18
  • no i want a value which is true if any of them is true and vice versa – Mandeep Chaudhary Apr 17 '18 at 14:19
  • 1
    Don't do this. Just use `bool& c = b.b1` or `c = b.b1` if you don't need it to modify – NathanOliver Apr 17 '18 at 14:19
  • @MandeepChaudhary Again, you didn't provide any real-world example of why you need to "convert from struct to a boolean value". What is the logic by which the totality of that `struct` can be expressed as a `bool`? to AND both members? XOR them? or what? – underscore_d Apr 17 '18 at 14:20
  • I use this because i have a struct of more than 100 memebers – Mandeep Chaudhary Apr 17 '18 at 14:21
  • That's another comment that does nothing to illluminate the question. By what logic should an instance of that struct evaluate to some boolean value? including which members? doing what with them? why? – underscore_d Apr 17 '18 at 14:21
  • 2
    This sounds like an XY problem. What are you actually trying to accomplish? – NathanOliver Apr 17 '18 at 14:22
  • @NathanOliver its a simple question if u have 100 memebrs in struct and any of them turns to be true then bool value to which it is to be converted will be true – Mandeep Chaudhary Apr 17 '18 at 14:22
  • 1
    "its a simple question" What, to a psychic? That's the first indication of any clarity you gave so far. – underscore_d Apr 17 '18 at 14:24
  • @underscore_d seriously is it that hard to understand ? – Mandeep Chaudhary Apr 17 '18 at 14:25
  • 1
    @MandeepChaudhary but I want my structure of 100 members to be true only when **all** of them are true, why it should work how you want it? And it looks like you need array/vector of bools not a struct – Slava Apr 17 '18 at 14:26
  • @MandeepChaudhary Yes. But keep trying to shift the blame onto readers for not magically inferring what you want, instead of yourself for writing a bad question. – underscore_d Apr 17 '18 at 14:27
  • 1
    There is no way to factor this out between unrelated members. Maybe you need an array so you can iterate over it? – Quentin Apr 17 '18 at 14:27
  • @Slava question is not will it be true or not question is how to convert it. Leave the logic on me. Please tell me how to convert it. Thanks – Mandeep Chaudhary Apr 17 '18 at 14:28
  • @underscore_d question is not will it be true or not question is how to convert it. Leave the logic on me. Please tell me how to convert it. Thanks – Mandeep Chaudhary Apr 17 '18 at 14:29
  • 2
    @MandeepChaudhary I am tellying you - check every member manually through operator `or` aka `||` but you better organize your data properly, then you can use `std::all_of` or `std::any_of` etc – Slava Apr 17 '18 at 14:30
  • 3
    You don't have any struct there. You have a struct type, that's a different thing. Also, the conversion you want to make won't be well-behaved C++ anyway. Perhaps something like bitset may meet your needs. – Frax Apr 17 '18 at 14:30
  • @Slava I appreciate your vision. But i need to know can i convert a struct having bool values into another variable of bool type using casting method. If yes then how ? – Mandeep Chaudhary Apr 17 '18 at 14:33
  • 1
    No, you can't. There is no way to say 'read this span of memory and summarise it to a `0` or `1`' (which would need to use member offsets, ignore struct padding, do things with memory for which there is no operator, etc.) – underscore_d Apr 17 '18 at 14:34
  • 1
    @MandeepChaudhary casting is not an option here at all. The best thinbg would be to write a member function that returns true if at least one of your bools is true. – Jabberwocky Apr 17 '18 at 14:35

4 Answers4

4

You cannot convert an instance of a struct to a bool where the value is the Boolean or of all it's members with just a cast. You need to tell the compiler how to make the object a bool and you do that by overloading the operator bool for the class. In there you do the logic to tell if it should be considered true or false. That would look like

struct Foo
{
    bool a = true;
    bool b = true;
    bool c = false;
    operator bool() { return a || b || c; }
};

int main()
{
    Foo f;
    std::cout << static_cast<bool>(f);
}

ouput:

1

If you have a lot of members like you said you should consider using an array instead of separate members so you can write a loop instead. C++ doesn't have reflection yet so there is no easy way to tell it to or together all the members.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • @NatahanOliver what is wrong with this type struct xs{ bool x :1 ; bool y :1; bool z :1; } zs; uint8_t* P = static_cast(static_cast(&zs)); – Mandeep Chaudhary Apr 18 '18 at 09:59
1

If you have control over the struct definition, this might be a good place to use bit-wise logic. If you have up to 128 boolean values, you could handle them them all within a couple 64-bit vars. To check an individual boolean, you'd use a mask to only check against the intended bit. And for the case described in the question, you could do a boolean-OR operation on the 64-bit vars. something like this:

struct b {
    uint64_t boolset_a;
    uint64_t boolset_b;
}

So if you had defined var_b to be of type struct b, you could do this to see if any of them were true: var_b.boolset_a || var_b.boolset_b

This should, I believe, be a more efficient methodology as it will not require 100+ boolean operations to see if any of them are true.

Christian Gibbons
  • 4,272
  • 1
  • 16
  • 29
  • That would just be manually reinventing a wheel that already exists: `std::bitset` and its indexing or `all`, `any`, or `none` methods, as it is specifically designed for dealing with fixed-size collections of bits. http://en.cppreference.com/w/cpp/utility/bitset The problem, though, is that the OP's stipulation of what is in these mysterious structures is vague but seems heavily to imply the members can't be changed. – underscore_d Apr 17 '18 at 18:00
  • @underscore_d you can blame the original tagging of the question for bringing in a C programmer to solve a C++ problem. – Christian Gibbons Apr 17 '18 at 18:05
0

I'd not do a cast but I'd use a member function with an explicit name:

int main()
{
  struct b {
    bool b1 = false;
    bool b2 = false;
    bool b3 = false;    
    bool AtLeastOneIsTrue() { return b1 || b2 || b3;  };
  };

  b str;
  str.b2 = true;
  cout << str.AtLeastOneIsTrue() << endl;

  str.b2 = false;
  cout << str.AtLeastOneIsTrue() << endl;
}

Output

1
0

But on the other hand if your struct has 100 different bool members, the AtLeastOneIsTrue function would be terrible. An array of bool or a vector of bool would be more appropriate then.

Sample using a vector:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
  struct b {
    vector<bool> values;

    b(int numberofbools) { values.assign(numberofbools, false); };  // constructor

    bool AtLeastOneIsTrue()
    {
      for (bool v : values)
      {
        if (v)
          return true;
      }

      return false;
    };

    void Set(int number, bool value)
    {
      values[number] = value;
    }
  };


  b str(100);   // str has 100 bool values, all false

  cout << str.AtLeastOneIsTrue() << endl;  // print1 0

  str.Set(3, true);                        // set value number 3 to true
  cout << str.AtLeastOneIsTrue() << endl;  // prints 1
}
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • what is wrong with this typestruct xs{ bool x :1 ; bool y :1; bool z :1; } zs; uint8_t* P = static_cast(static_cast(&zs)); – Mandeep Chaudhary Apr 18 '18 at 09:58
  • 1
    @MandeepChaudhary It's undefined behaviour. Read this [SO article](https://stackoverflow.com/questions/11442708/type-punning-and-unions-in-c) about type punning – Jabberwocky Apr 18 '18 at 10:10
0

IMHO, your better create a member function or an operator for the struct, like shown by NathanOliver, that operates on the booleans in there. In fact, your could create at least two member functions, one that tells you whether any of the booleans is true, and other that tells you if all are true.

My approach, as this will probably need to be extendable in some sense in a normal project in the future, is to use a vector of booleans, or better a map, so that each boolean can be given a name, and then two functions (methods if they belong to a bigger class, like a configuration entity) that provide the all/any computation on those flags.

A quick and dirty example of this approach is shown below (compile with C++11 activated, for the auto loop, or modify otherwise):

#include <iostream>
#include <string>
#include <map>

using namespace std;

typedef map<string, bool> Flags;

bool allOK(Flags & fl) {
    bool result = true;
    for (auto & kv : fl) { result &= kv.second; }
    return result;
}

bool anyOK(Flags & fl) {
    bool result = false;
    for (auto & kv : fl) { result |= kv.second; }
    return result;
}

int main(int argc, char * arg[])
{
    Flags flags;

    flags["a"] = true;
    flags["b"] = true;
    flags["the_third_flag"] = false;

    cout << "1. ALL OK: " << boolalpha << allOK(flags)
         << " - ANY OK: " << anyOK(flags) << '\n';

    flags["the_third_flag"] = true;
    cout << "2. ALL OK: " << boolalpha << allOK(flags)
         << " - ANY OK: " << anyOK(flags) << '\n';

    flags["a"] = false;
    flags["b"] = false;
    flags["the_third_flag"] = false;
    flags["a_last_flag"] = false;
    cout << "3. ALL OK: " << boolalpha << allOK(flags)
         << " - ANY OK: " << anyOK(flags) << '\n';

    return 0;
}
J C Gonzalez
  • 861
  • 10
  • 23