tags:

views:

4921

answers:

14

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?

+3  A: 

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;
}
JaredPar
+1: It would be better if C++ had closures. I guess you could simulate them with function pointers. (PS: Don't like the class name).
graham.reeds
+1  A: 

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.

Dan Olson
A: 

Hi

I guess bool is uninitialized by default and remains so until you assign a value (true/false) to it

cheers

Andriyev
Why guess when it causes people to vote you down?
Max Lybbert
That's true that unitialized automatic bool might behave as it is neither true or false. But the question is a bit cryptic and whether this information is related...
Anonymous
This would only be useful if you could do "if (mybool == std::uninitialized_bool) {...}", which you can't. So the OP's problem remains unresolved.
Daniel Daranas
+2  A: 

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

Laurence Gonsalves
+1  A: 

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.

Greg Hewgill
+13  A: 

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

Josh Kelley
You can even set up boost::tribool for your DailyWTF needs: BOOST_TRIBOOL_THIRD_STATE( FILENOTFOUND).
Michael Burr
+14  A: 

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;
Steven Canfield
Stolen from thedailywtf.com? :)
JaredPar
Funny for the DailyWTF reference.
Greg Hewgill
haha nice reference
GMan
I like the answer but i would tweek it a bit to include a DEFAULT instead of FILENOTFOUND, so i posted a another version of the answer
Azder
StackOverflow would just not be complete without this answer in a wholly relevant context; I thank you.
aib
http://thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx
rlbond
Nice touch having TRUE == false and FALSE == true.
Motti
If you don't initialize a bool, then it can even be *neither* true *nor* false, which is very evil indeed (undefined).
Johannes Schaub - litb
A: 

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.

John Millikin
A: 

I like the enum version answers, but I usually like adding some null value, and also in this case you could use a default one too. Example:

typedef enum {
  // Uncomment if you want a null value possible
  // NONE -1,
  // You could use c++ value for TRUE instead of 1 
  TRUE = 1,
  // You could use c++ value for FALSE instead of 1 
  FALSE = 0,
  /*
    You could initialize DEFAULT 
    to TRUE or FALSE, 
    but then you marry that value 
    for future versions of the interface
  */
  DEFAULT 
} MYBOOL ;
Azder
You just DID set DEFAULT = TRUE, whether you intended to or not.
Ben Voigt
+11  A: 

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

In other words, 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);
Daniel Daranas
A: 

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

class MyClass {
  public:
    MyClass(bool bFlag); // <-- not default
    MyClass(void);       // <-- default
};
Marc Bernier
This is similar to what existed already that I was told to clean up :)
greenguy1090
+2  A: 

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;
   }
}
Paul Hilbert
A: 
class aclass
{
    <stuff> lots of other things
    bool mybool
    bool ismyboolinit

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

}
Pod
A: 

struct Bool { //guaranteed initialized bool bool v;

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

};

VladT