Reputation: 329
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
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
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
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
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
Reputation: 4130
class aclass
{
<stuff> lots of other things
bool mybool
bool ismyboolinit
void setmybool(bool b)
{
mybool = b;
ismyboolinit = true;
}
}
Upvotes: 0
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
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
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
Reputation: 58352
It sounds like you want boost::tribool or maybe boost::optional<bool>.
Upvotes: 18
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:
bool
value to indicate whether the value is "default" or not, orI would probably choose option 1.
Upvotes: 4
Reputation: 143094
You could have a separate private member that indicates whether the bool value has actually been initialized or not.
Upvotes: 2
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
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