voteblake
voteblake

Reputation: 329

Default value for bool in C++

I'm redesigning a class constructor in C++ and need it to catch an unspecified bool. I have used default values for all of the other parameters, but from my understanding bool can only be initialized to true or false. Since both of those cases have meaning in the class, how should I handle checking for change from a default value?

Upvotes: 14

Views: 57374

Answers (13)

Paul Hilbert
Paul Hilbert

Reputation: 31

Use the great boost::optional. And not only for bools but for all other places you used some dirty not-initialized-values in. It is used like this:

void function(optional<int> value) {
   if (value)
      std::cout << "value is defined: " << value.get() << "\n";
   else
      std::cout << "value is not defined\n";
}

And here's a function example returning an optional:

struct MapClass {
   map<string,int> m_map;

   optional<int> getValue(string key) {
      optional<int> result = none;
      if (m_map.find(key) != m_map.end())
         result = m_map[key];
      return result;
   }
}

Upvotes: 3

VladT
VladT

Reputation: 310

struct Bool { //guaranteed initialized bool
    bool v;

    Bool() : v(false) {}
    operator bool() const { return v; }
    bool& operator=(const bool val){ return v = val; }
};

Upvotes: 3

Daniel Daranas
Daniel Daranas

Reputation: 22624

Tristate bool is the path to the dark side. Tristate bool leads to anger. Anger leads to hate. Hate leads to suffering.


Prefer not to use a tristate bool.

Instead, use one additional boolean for whether the first boolean is "initialized" (or better, "known") or not.

class Prisoner : public Person
{


  ...

  bool is_veredict_known;
  bool is_guilty;
}

If the veredict is not known yet, you can't tell if the Prisoner is really guilty, but your code can differentiate between the different situations. Of course the Constitution assures that the default value of is_guilty should be false, but, still... :)

By the way, the class invariant should include:

assert(is_veredict_known || !is_guilty);

Upvotes: 38

Rob
Rob

Reputation: 1

Well if your using functions and classes, just overload them.

ie:

    class thing
{
  public:
   void f1(bool); // bool input
   void f1(int = 3); // default with out bool being known
  private:
   // stuff
};     
void thing::f1 (bool hasAFace)
{
  if(hasAFace)
   f1(0);
  if(!hasAFace)
   f1(1);

}

void thing::f1 (int tri)
{
  bool actionTime;
  if(tri == 1)
    actionTime = true;
   else if(tri == 0)
    actionTime = false;
   else
    //input defualt action here.
} 

// and there you go. Also you don't need to have a class you could just use overloaded functions.

Upvotes: 0

Pod
Pod

Reputation: 4130

class aclass
{
    <stuff> lots of other things
    bool mybool
    bool ismyboolinit

    void setmybool(bool b)
    {
        mybool = b;
        ismyboolinit = true;
    }

}

Upvotes: 0

Marc Bernier
Marc Bernier

Reputation: 2996

You really can't. Could you provide a second constructor, for example:

class MyClass {
  public:
    MyClass(bool bFlag); // <-- not default
    MyClass(void);       // <-- default
};

Upvotes: 1

Steven Canfield
Steven Canfield

Reputation: 7332

The reality is that you can't do this. A bool has value, either true or false, and if you haven't initialized it then it is randomly true or false, possibly different at each run of the program or allocation of that class.

If you need to have a type with more options, define an enum.

typedef enum MyBool {
    TRUE,
    FALSE,
    FILENOTFOUND
} MyBool;

Upvotes: 39

John Millikin
John Millikin

Reputation: 200746

Instead of a boolean, use an enumeration. For example, to control the level of magic:

enum {
    MY_ENUM_NO_MAGIC,
    MY_ENUM_SOME_MAGIC,
    MY_ENUM_MORE_MAGIC
} MagicLevel;

Then have your constructor accept a parameter MagicLevel magic = MY_ENUM_NO_MAGIC.

Upvotes: 0

Josh Kelley
Josh Kelley

Reputation: 58352

It sounds like you want boost::tribool or maybe boost::optional<bool>.

Upvotes: 18

Greg Hewgill
Greg Hewgill

Reputation: 992847

In C++ a bool is only one bit of information, either a 0 or a 1. Since you want to represent three possible states, you need one more bit of information. There are two general techniques:

  1. Use another bool value to indicate whether the value is "default" or not, or
  2. Use an enumeration type with three values to indicate (default, true, false).

I would probably choose option 1.

Upvotes: 4

Laurence Gonsalves
Laurence Gonsalves

Reputation: 143094

You could have a separate private member that indicates whether the bool value has actually been initialized or not.

Upvotes: 2

Dan Olson
Dan Olson

Reputation: 23367

I don't quite understand, but I'll try...

Default values are applied when you have an aggregate initializer that leaves some values unspecified. In that case, bool's default would be false. In a class, the "default" value would be uninitialized, meaning it could be any value and could change from run to run.

If you're interested in whether or not a bool has changed, your best option is to keep track of it with a second bool defaulting to false, or use an enum representing 3 possible states. If you truly want 3 states, you really don't want a bool.

Upvotes: 1

JaredPar
JaredPar

Reputation: 754575

If that's what you need, create a value which represents the concept of a value that may not have been initialized.

template <typename T>
struct Maybe {
  Maybe() : m_hasValue(false) {}
  bool HasValue() const { return m_hasValue; }
  T& Value() { ThrowIfFalse(m_hasValue); return m_value; }
  const T& Value() const { ThrowIfFalse(m_hasValue); return m_value; }
  void SetValue( _In_ const T& value) { m_value = value; m_hasValue = true; }
private:
  bool m_hasValue;
  T m_value;
};

Now you can represent all 3 states you need.

class SomeType { 
  ...
  Maybe<bool> m_myBool;
}

Upvotes: 5

Related Questions