How to have a tri-state 'boolean' in c++ - c++

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

You might want to look at boost.tribool: http://www.boost.org/doc/libs/1_60_0/doc/html/tribool.html

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
{}

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.

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.
Source: http://www.boost.org/doc/libs/1_60_0/libs/optional/doc/html/boost_optional/a_note_about_optional_bool_.html

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;
}

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

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;

Related

Is it defined behaviour to assign to function call in or in if (C++17)

During a codebase refactor I found code like this:
void myFunction (std::map<int, int> my_map)
{
int linked_element;
if (my_map[linked_element = firstIndex] != 0
|| my_map[linked_element = secondIndex] != 0)
{
// do some stuff with linked_element
}
}
Or
void myFunction (std::set<int> my_set)
{
int linked_element;
if (my_set.find(linked_element = firstIndex) != my_set.end()
|| my_set.find(linked_element = secondIndex) != my_set.end())
{
// do some stuff with linked_element
}
}
From what I understood the aim of that was to avoid checking 2 times (first when entering in the if, second when assigning the variable).
I can understand that depending on which side of the || is true linked_element will be assigned to the right value but this still feels kind of bad to me.
Is this kind of behaviour defined?
This behavior is well defined by the order of evaluation.
First, the linked_element = firstIndex assignment happens. This expression returns the value of firstIndex, that is then used as an argument for the subscript operator on my_map (i.e., my_map[linked_element = firstIndex]). The return value from that expression is checked against the != 0 condition. If it's true, the other side of the || operator is not evaluated due to short-circuit logic. If it's false, the same story happens on the other side of the operator.
Whether or not it's a good practice to write code in such a style is a different question though. Personally speaking, I'd prioritize readability and maintainability over this micro-optimization unless it's a super-critical piece of the program, but it's a matter of opinion, I guess.
In original code behavior is well defined, since operator || evaluates first argument and if this is evaluated to false evaluates second argument.
BUT: Assignment there is confusing and many (probably all) static analyzes tools will complain about this. So I would reflector this code in this way, so it would require less brain power to read:
void doSomeStuff(const std::set<int>& my_set, int linked_element)
{
.....
}
void myFunction (const std::set<int>& my_set)
{
if (my_set.find(firstIndex) != my_set.end())
{
doSomeStuff(my_set, firstIndex);
} else if (my_set.find(secondIndex) != my_set.end()) {
doSomeStuff(my_set, secondIndex);
}
}
Since you had to ask question about this code this proves that original version is bad from maintainer point of view. Code which requires lots of focus to understand is costly in maintenance.
BTW this fragment of code:
if (my_map[linked_element = firstIndex] != 0
looks suspicious. I have even more suspensions seeing set-version.
This looks like that someone do not understand how operator[] works for maps. If value for key do not exist, default value is introduced to map. So checking for default value 0 seem like attempt to adders this issue. Possibly my_map.count(firstIndex) should be used.
An alternate version, assuming firstIndex and secondIndex are literal values (like 2 and 7), or are otherwise known relative to some invalid third index value:
void myFunction (std::set<int> & my_set)
{
int linked_element =
my_set.contains (firstIndex) ? firstIndex :
my_set.contains (secondIndex) ? secondIndex :
thirdIndex;
if (linked_element != thirdIndex)
{
// do some stuff with linked_element
}
}
If the indices are not known then a std::optional<int> can step in here too.
If pre-C++20, replace .contains() with .count().
Bigger concerns with the original code are:
the pass-by-value of a potentially large container (never assume COW)
map[index] silently adds the index to the map if not present

Safely convert enum class from underlying type

Let's say I have a strongly typed enum type like this:
enum class message : int {
JOIN = 0,
LEAVE = 4,
SPAWN = 1,
}
And I need to safely (safely in this case means discarding invalid variants) convert it from it's underlying type (int).
For this purpose, I have a function to convert it for me:
std::optional<message> get_message(int num) {
return num == (int)message::JOIN || num == (int)message::LEAVE || num == (int)message::SPAWN ? (message)num : {};
}
This works, but is long to write and prone to mistakes, especially for enums with a larger number of variants.
Is there a way to automate this process in C++17?
Talking about underlying type, we notice that this class merely obtains a type using another type as model, but it does not transform values or objects between those types.
As an option to simplify the function you could work by iterating in the enum,or as others said before with some type of container, by iterating the same enum as an example here: How can I iterate over an enum?
and more information about enum just in case: https://learn.microsoft.com/en-us/cpp/cpp/enumerations-cpp?view=vs-2019

Using enum in loops and value consistency

I'm a big fan of C++'s strong-typing features and what I like the most is to use enumerations while dealing with limited sets of data.
But enumerations lack some useful features, for example operators:
enum class Hex : int
{
n00, n01, n02, n03,
n04, n05, n06, n07,
n08, n09, n10, n11,
n12, n13, n14, n15
};
for (Hex h = Hex::n0; h <= Hex::n15; ++h) // Oops! no 'operator ++'
{ /* ... */ }
Is easy to get rid of the lack of operators creating a free operator on the same scope:
Hex &operator ++(Hex &h)
{
int r = static_cast<int>(Hex);
h = static_cast<Hex>(r + 1);
return h;
}
for (Hex h = Hex::n0; h <= Hex::n15; ++h) // Now the '++h' works!
{
std::cout << std::dec << int(h) << ": "
<< std::hex << int(h) << '\n';
}
But this approach is more a nuisance than a solution, because it can break the value limitation of the enumeration: applying ++h while h equals to Hex::n15 will set h to he value 16, wich is out of the Hex scope of values while h is still of the type Hex!, This problem is more evident in other enumerations:
enum class Prime : int
{
n00 = 2, n01 = 3, n02 = 5, n03 = 7,
n04 = 11, n05 = 13, n06 = 17, n07 = 19,
n08 = 23, n09 = 29, n10 = 31, n11 = 37,
n12 = 41, n13 = 43, n14 = 47, n15 = 53
};
Prime &operator ++(Prime &p)
{
// How to implement this?! will I need a lookup table?
return p;
}
This problem was a surprise for me; I was betting that storing an incorrect value into an enumeration value will throw an exception. So, for now I was wondering if there's an elegant way to deal with this enumeration's weaknesses, the goals I want to achieve are:
Find a comfortable way to use enumeration values in loops.
Ensuring enumation data consistency between operations.
Additional questions:
Is there a reason for not throwing an exception when an enumeration data gets a value that is out of its possible values?
There is a way to deduce the type associated with an enumeration class?, the int type in the enumerations Hex and Prime.
As you've noticed, enum in C++ is not an enumerated type,
but something more complex (or more mixed). When you define an
enum, you define in fact two things:
An integral type with a legal range sufficient to contain an
or of all of the enumerated values. (Technically: the range
is 2^n - 1, where n is the number of bits necessary to
hold the largest value.)
A series of named constants having the newly defined type.
(I'm not sure what happens with regards to the range if you
explicitly specify an underlying type.)
Given your enum Prime, for example, the legal values would be
all integers in the range [0...64), even if all of these
values don't have a name. (At least if you didn't specifically
say that it should be an int.)
It's possible to implement an iterator for enums without
initializers; I have a program which generates the necessary
code. But it works by maintaining the value in an integral type
which is large enough to contain the maximum value plus one. My
machine generated implementations of ++ on such an enum will
assert if you try to increment beyond the end. (Note that
your first example would require iterating h one beyond the
last value: my implementation of the various operators does not
allow this, which is why I use an iterator.)
As to why C++ supports the extended range: enum are often used
to define bit masks:
enum X
{
a = 0x01,
b = 0x02,
c = 0x04,
all = a | b | c,
none = 0
};
X operator|( X lhs, X rhs )
{
return X((int)lhs | (int)rhs);
}
// similarly, &, |= and &=, and maybe ~
One could argue that this use would be better handled by
a class, but the use of enum for it is ubiquitous.
(FWIW: my code generator will not generate the ++, -- and
the iterators if any of the enum values has an explicitly
defined value, and will not generate |, & etc. unless all of
the values have explicitly defined values.)
As to why there is no error when you convert some value outside
the legal range (e.g. 100, for X, above) is simply in keeping
with the general philosophy inherited from C: it's better to be
fast than to be correct. Doing extra range checking would
entail additional runtime cost.
Finally with regards to your last example: I don't see this as
a realistic use of enum. The correct solution here is an
int[]. While the C++ enum is rather a mixed breed, I would
only use it as a real enumerated type, or for bit masks (and
only for bit masks because it is such a widely established
idiom).
You can use a switch:
class Invalid {};
Prime& operator ++(Prime& p)
{
switch(p)
{
case n00: return n01;
case n01: return n02;
case n02: return n03;
case n03: return n04;
case n04: return n05;
case n05: return n06;
case n06: return n07;
case n07: return n08;
case n08: return n09;
case n09: return n10;
case n10: return n11;
case n11: return n12;
case n12: return n13;
case n13: return n14;
case n14: return n15;
// Here: 2 choices: loop or throw (which is the only way to signal an error here)
case n15: default: throw Invalid();
}
}
But note that this is not the right use of enums. I personally find this error-prone. If you want to enumerate integers, you can use an array of ints to do this, or for the case of prime numbers, a function (in mathematical sense: int nextPrime(int)).

Is there a better way to initialize an array?

Given an array map with size of 256, what is the best way to initialize it so that each element is false?
bool map[256];
for (int i=0; i<256; i++)
{
map[i] = false;
}
Thank you
bool map[256] = { false };
edit: for a reference to the standard as to why this is legal, see the answers below.
bool map[256] = {false};
(C++ also allows bool map[256] = {};. The above works in C too.)
This will set map[0] to false, and "default-initialize" the rest of 255 members (C++98 §8.5.1/7: "If there are fewer initializers in the list than there are members in the aggregate, then each member not explicitly initialized shall be default-initialized"; C99 §6.7.8/21).
For bool, "default-initialize" means set to (bool)0, i.e. false (C++98 §8.5/5; C99 §6.7.8/10).
Note that this method doesn't work if you want to initialize to true.
Like this:
bool map[256] = { 0 };
Some would say this:
bool map[256] = {};
But to me that just looks a little weird.
Why use "0" rather than "false"? It's not a big deal, but I do it because the array initializer is in effect padded out to the size of the array with 0, not with copies of the first element. Since the initialization of elements 1 through 255 is defined in terms of the value "0" (which of course converts to false), I see no harm in element 0 being initialized with "0" too. Having a "0" at the end of a too-short initializer list for scalar types reminds me of what's really going on.
Specifically, the standard defines this at 8.5.1/7 (initializer list shorter than array), and 8.5/5 (value-initializing a bool is equivalent to initializing it with the value 0 converted to bool).
Absent a reason to do otherwise, the best choice is probably to use a vector:
std::vector<bool> map(256, false);
vector<bool>, however, is a specialization that's rather different from what you might expect. Depending on the situation, you might prefer:
std::vector<char> map(256, false);
In C++, X = { 0 } is an idiomatic universal zero-initializer. This was a feature carried forward from C.
bool map[256] = { 0 };

Is there a way to find the cardinality (size) of an enum in C++?

Could one write a function that returns the number of elements in an enum? For example, say I have defined:
enum E {x, y, z};
Then f(E) would return 3.
Nope.
If there were, you wouldn't see so much code like this:
enum E {
VALUE_BLAH,
VALUE_OTHERBLAH,
...
VALUE_FINALBLAH,
VALUE_COUNT
}
Note that this code is also a hint for a (nasty) solution -- if you add a final "guard" element, and don't explicitly state the values of the enum fields, then the last "COUNT" element will have the value you're looking for -- this happens because enum count is zero-based:
enum B {
ONE, // has value = 0
TWO, // has value = 1
THREE, // has value = 2
COUNT // has value = 3 - cardinality of enum without COUNT
}
There are ways, but you have to work... a bit :)
Basically you can get it with a macro.
DEFINE_NEW_ENUM(MyEnum, (Val1)(Val2)(Val3 = 6));
size_t s = count(MyEnum());
How does it work ?
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/size.hpp>
#define DEFINE_NEW_ENUM(Type_, Values_)\
typedef enum { BOOST_PP_SEQ_ENUM(Values_) } Type_;\
size_t count(Type_) { return BOOST_PP_SEQ_SIZE(Values_); }
Note that length could also be a template specialization or anything. I dont know about you but I really like the expressiveness of a "Sequence" in BOOST_PP ;)
No, this is a VFAQ and the answer is NO!!
Not without kludging anyway.
Even that trick about with a final entry only works if none of the values are non-default. E.g.,
enum B {
ONE, // has value = 0
TWO, // has value = 1
THREE=8, // because I don't like threes
COUNT // has value = 9
}
No. For one thing, you can't take types as parameters (just instances of types)