Reputation: 827
What is the best way to have three value Boolean variable in c++?
I would like to have fields set to true
, false
or not set at all in my array.
If I declare them this way:
t[0] = true;
t[1] = false;
t[2] = NULL;
When I test the condition I get:
t[2]
is false
Upvotes: 9
Views: 16250
Reputation: 1585
I also believe an enum declaration is the cleaner and simplest solution.
A small note on the size of the new type: enums are usually (depending of course on the compiler) backed by integers, so you are allocating something like 32 or 64 bits to actually use 2 bits.
In newer C++ (C++11), you can specify the underlying type of the enum (to an existing integral type). For example:
enum tribool: uint8_t {False = 0, True = 1, Unknown = 2};
...
enum tribool f = tribool::False;
Upvotes: 2
Reputation: 1277
This should work:
t[0] = true;
t[1] = false;
t[2] = -1;
Or if you only need 3 states but perhaps would like more at some point, an enum
is great:
enum STATES
{
NULL_STATE = -1, // you can manually specify -1 to give it a special case value
FALSE, // will be equal to 0
TRUE // will be equal to 1
};
No matter what though, 0/false
is the only thing that returns false
in an if()
statement. -1
and true
both return true
.
You may want to use a switch like this to deal with 3+ states:
switch (var) // may need to cast: (int)var
{
case 1:
case 0:
case -1:
};
Alternatively if you want to stick to an if statement block, you could do something like this:
if (var == -1) // or (var == NULL_STATE)
{}
else if (var) // true condition
{}
else // false
{}
Upvotes: 6
Reputation: 10998
You can use std::optional
for this:
std::optional<bool> t[3];
t[0] = true;
t[1] = false;
t[2] = std::nullopt;
for (auto const& i : t)
if (i.has_value()) std::cout << i.value() << '\n';
output:
1
0
Upvotes: 5
Reputation: 297
What is the best way to have three value Boolean variable in c++?
Boolean values by definition only have 2 possible states - True or False. If you want to have another state for 'invalid' or 'not set' then you need to encapsulate the bool variable in some other data-types.
The right solution depends on what you want to do with that variable. For simple comparisons (if-else and switch) scoped enums (c++11) should be preferred.
enum class tristate{true,false,undefined=0};
They are simple, easy to use and understand and offer type safety over plane old enums. As they are type-safe you can not accidentally compare it with different types of enums or numeral types, But it also means you can not use bitfiddling and integer-tricks either. Unless a different type is specified an enum class is a numerical type which gets initialized to '0'. that means by assigning the value '0' to one of the enum-values you can make that the default state.
tristatet[7];
t[1] = tristate::true;
t[2] = tristate::false;
t[3] = tristate::undefined;
t[4] = false; //error
t[5] = 0; //error
t[6] = null; //error
t[0] == true; //error
t[0] == tristate::true; // false
t[0] == tristate::undefined; // true
Of course you can use that in a switch-statement:
switch(t[2]) {
case tristate::true:
foo(); break;
case tristate::false:
bar(); break; //t[2] was set to tristate::false
case tristate::undefined :
doNothing(); break;
}
Upvotes: 3
Reputation: 234685
Consider using std::experimental::optional<bool>
(if your C++ standard library has it), or boost::optional<bool>
(www.boost.org).
I believe std::optional
is a candidate for C++17 so if you adopt one of the above then your refactoring effort to C++17 ought to be minimal.
If you don't like using things that are not (yet?) in the "proper" C++ standard library, then consider
Something based around std::unique_ptr<bool>
A std::pair<bool, bool>
A good old-fashioned enum
with 3 values.
Upvotes: 6
Reputation: 7588
You could use boost::optional
http://www.boost.org/doc/libs/1_60_0/libs/optional/doc/html/index.html
boost::optional<bool> myBooleanVariable;
I agree that tribool can be better if you don't need the uninitialised values to be NULL. Where comparing optional and tribool, the documentation says:
First, it is functionally similar to a tristate boolean (false, maybe, true) —such as boost::tribool— except that in a tristate boolean, the maybe state represents a valid value, unlike the corresponding state of an uninitialized optional. It should be carefully considered if an optional instead of a tribool is really needed.
Upvotes: 3
Reputation: 3365
You might want to look at boost.tribool: http://www.boost.org/doc/libs/1_60_0/doc/html/tribool.html
Upvotes: 8