Using std::map inside switch case - c++

I have this:
map<string,int> a;
int b;
And i'd like to make this:
switch(b)
{
case a["someStr1"]:
someCode1();
break;
case a["someStr2"]:
someCode2();
break;
etc.
}
But it doesn't compiles. How to implement this correctly?

switch conditions need to be constants, so what you want to do here is not possible.
You're better off using some if statements.

switch/case are meant for constants (e.g., enum, ints etc.).
You can use the map<>::iterator to run through the values and compare with b.
for(map<string,int>::const_iterator it = a.begin(), end = a.end(); it != end; it++)
{
if(it->second == b)
{
...
break;
}
}
This way you can avoid the code duplication for comparison, if your a is large enough.
Also, you can explore the option of replacing for loop with for_each.

You can't.
Expression after case in a switch statement must be integral compile-time constant. So a literal (42), const int variable initialized with a literal (const int x = 66 ... case x:) or enum value. And thats about it.
The reason this is so strict is efficiency. Compilers usually create labels for each case and if you know the value for each label at compile time, you can make some nice optimizations that avoid most of the overhead a normal code branching has.
In your case just go with if-else:
if(b == a["someStr1"]) {
//...
} else if(b == a["someStr2"]) {
//...
} // and so on

Related

How to have a tri-state 'boolean' in 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;

Is there a NULL equivalent for pairs in C++?

What would I want to use instead of NULL if I have an unassigned pair in C++?
As an example, suppose I have (pseudo)code like the following:
pair<int,int> bestPair; //Global variable
updateBestPair(vector<int> a, vector<int> b) {
bestPair = NULL;
for (/* loop through a and b */) {
if (/* pair(a,b) is better than bestPair and better than some baseline */)
bestPair = make_pair(a,b);
}
if (bestPair != NULL) //Found an acceptable best pair
function(bestPair);
else
cout<<"No acceptable pairs found"<<endl;
}
Is there a NULL equivalent for pairs in C++?
No.
What would I want to use instead of NULL if I have an unassigned pair in C++?
Here are a few options:
you can use a pointer to a pair, which can be set to NULL; This is probably not the best solution (since you are clearly not requiring a pointer)
you can use a boost::optional<std::pair<int,int>>;
you can (and probably should) rewrite your code not to use a global variable.
you can restructure your control flow to avoid checking for a valid pair as a separate step:
pair<int,int> bestPair; //Global variable
updateBestPair(vector<int> a, vector<int> b) {
// not needed
// bestPair = NULL;
//loop through a and b
if (/* pair(a,b) is better than bestPair and ... */)
{
bestPair = make_pair(a,b);
function(bestPair);
}
else
cout<<"No acceptable pairs found"<<endl;
}
you can choose an artificial value to represent "invalid pair value":
// use as constant, wherever you used NULL before
const auto invalid_pair = std::make_pair(
std::numeric_limits<int>::max(),
std::numeric_limits<int>::max());
you can use a boolean flag:
pair<int,int> bestPair; //Global variable
updateBestPair(vector<int> a, vector<int> b) {
bool initialized = false;
//loop through a and b
if (/* pair(a,b) is better than bestPair and ... */)
{
bestPair = make_pair(a,b);
initialized = true;
}
if(initialized)
function(bestPair);
else
cout<<"No acceptable pairs found"<<endl;
}
you can use a custom solution (similar to boost::optional wrapper or not)
No. C++ objects cannot be "NULLed".
(Even pointers, which are objects, cannot be "NULLed"! This is confusing because their value may be set to a null pointer value, which we sometimes in the past obtained with a macro named NULL; however, this has never been the same as "NULLing" the pointer itself. Er, anyway…)
I recommend either boost::optional, or rethink the idea of having a global variable that can be "has a useful value" or "does not have a useful value". What's the point in it existing if it has no useful value?
No, that is not possible. You could use an additional variable to indicate the validity of the pair (that you have a pair).

Comparing a char to chars in a list in C++

Is there a way to compare a char to each element in a list of chars?
char ch;
if(ch == 'a' || ch == 'b' || ch == 'c')
Is there some way to just do
if(ch is one of {a, b, c})
Why would you write lambdas or use a throwaway string object when you can just:
if (strchr("abc", ch))
Use : std::any_of
With C++11 :
std::string str="abc";
if(std::any_of(str.cbegin(), str.cend(),
[ch](const char& x){return x==ch; } ))
{
}
Or use a functor:
struct comp
{
comp(char x) :ch(x){}
bool operator()(const char& x) const
{
return x == ch;
}
char ch;
};
And then,
if(std::any_of(str.cbegin(), str.cend(),comp(ch) ))
{
}
Edit : std::any_of might not be efficient enough, just for sake of C++'s <algorithm> one can try this out too .
You could use std::find. Assuming chars is your character array and you need to find ch.
if(std::find(std::begin(chars), std::end(chars), ch) != std::end(chars))
One way to do it is searching a string, like this:
string abc("abc");
if (abc.find(ch) != string::npos) {
...
}
(This answer really only applies if you don't want to use C++ std lib constructs.)
In your specific case, you should be able to do:
if(ch >= 'a' && ch <= 'c')
I also have employed fall-through switch for this case:
switch(ch)
{
case 'a':
case 'b':
case 'c':
case 'e':
...
break;
}
Some people don't like fall-through switch/case statements, but I think its less error prone than a massive piece of boolean logic and will perform better than using a data structure for this purpose. The compiler is really good with dealing with switch statements.
If you can use variadic template arguments, which were introduced in C++11, then you can do something like this:
template <typename Key, typename Value>
inline bool in(const Key& key, const Value& value) {
return key == value;
}
template <typename Key, typename Value0, typename ...ValueN>
inline bool in(const Key& key, const Value0& value, ValueN &&...args) {
return (key == value ? true : in(key, std::forward<ValueN>(args)...));
}
I use it for strings like this:
if (in(some_string, "base", "os", "io", "coroutine", "debug")) ...
But other types that support comparison (char is one of them) should also work.
Hope it helps. Good Luck!
Just as another option, create a set with the characters, and check if it's contained there;
std::set<char> mySet = {'a','b','c'}; // C++11 initializer list
if(mySet.find('d') != mySet.end()) {
...
}
I'm sort of surprised that nobody suggested find_first_of.
char c('e');
// we can check if c is undesirable
const std::string unwanted("abc");
bool undesirable = (unwanted.find_first_of(c) != std::string::npos);
// OR we can check if c is desirable
const std::string wanted("def");
bool desirable = (wanted.find_first_of(c) != std::string::npos); //..or check if it's desirable.
I use this (maybe I shouldn't? folks?) for ignoring unwanted characters from a string iterator...
/** in and out are string iterators.
* skip over any undesirable characters by matching
* against desirable and looking for npos.
**/
const std::string ok("!+-./0123456789:^ABFIORmn");
while (ok.find_first_of(*in) == string::npos && in < out) {
in++;
}
A nice benefit of this is that by putting more frequent characters at the front of the string, there's a little bit of saving in time.

How to make the C++ precompiler do a "loop"

I want to simplify the following code:
switch (index)
{
case 1:
output = function1();
break;
case 2:
output = function2();
break;
case 3:
output = function3();
break;
....
Where index is a compile time constant.
If I would use a precompiler macro, I would need to use it n times, where n is the number of cases. How can I reduce the above mentioned code to O(1) lines of code?
Try this (assuming function 1-n are the real names. and that index is, as you say, a compile time constant):
#define CALLFUNCTION(x) function##x()
output = CALLFUNCTION(1);
correction: this will not work for variables, will work if the constant is used directly. This might defeat the purpose if the provided code is all there is in each case statement.
There is no need to do a switch at all. Alternatively you could use template specialization.
template<int index> function();
output = function<index>();
and specialize the function template for each index.
template<> function<1>(){return 1;} // or {return function1();}
If it is not a compile time constant, you need to generate the switch like Fomin Arseniy suggests. Another option would be to use a array of function pointers
You cannot do it with a macro - but this will work (I think):
int (*functions[])() = { &function1, &function2, &function3};
int output = functions[index]();
May be supermacro can slightly simplify your work.
Simply create "counter.def" file with code:
COUNTER(1)
COUNTER(2)
COUNTER(3)
#undef COUNTER
Then in any case of using switch or any other construction with repeating counting
switch(index)
{
#define COUNTER(i) case i: output = function##i(); break;
#include "counter.def"
}
Late to the party, since then it's useful to check boost libraries on it:
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#define DECL(z, n, _) case n: (function ## n)(); break;
BOOST_PP_REPEAT_FROM_TO(1, 3, DECL, _)
However, if you're in a somewhat newer C++, it's recommended to use template metaprogramming and if constexpr () instead.

comparison operator

It may be silly question.
Is there any way to give comparison operator at runtime using string variable.
Suppose i have a data of salaries in vector.
vector < int > salary;
Input:
salary[i] != /* ==,>,<,>=,<= (any comparison operator)) */ 9000.
The input given like above. I store the comparison operator in string str. str = (any comparison operator). Is there any way to check like this without if and switch.
salary str 9000
You can create a map with operator-strings as keys and function objects for corresponding comparison operations as values.
Creating a map:
std::map<std::string, boost::function<bool(int, int)> > ops;
ops["=="] = std::equal_to<int>();
ops["!="] = std::not_equal_to<int>();
ops[">"] = std::greater<int>();
ops["<"] = std::less<int>();
ops[">="] = std::greater_equal<int>();
ops["<="] = std::less_equal<int>();
Using it:
bool resultOfComparison = ops[str](salary[i], 9000);
(See this link for a complete working example.)
EDIT:
As #sbi said in the comments below, accessing a map using map[key] will create an entry if the key didn't exist. So use it = map.find(key) instead. If the result is equal to map.end() the key wasn't found, otherwise value is it->second. Take note of this while adapting this solution to your needs.
Still, you might have a std::map with a mapping between contents of your strings and pointers to your operators.
No. Not possible. Unless you parse the given input and call the corresponding operation. In any case, you would need a if - else statement.
You need to have something of sort of EVAL in your programming language, which evaluates your strings.
EDIT: C++ does not have EVAL to support your cause.
No, compiled languages like C++ don't work like that. There has to be code in the final executable that does the comparison, and by design C++ doesn't generate that code unless it's actually in the source program.
You can also create a functor which will take string as a constructor or factory which will produce different functors (depending on flexibility you need).
So something like:
:Input
Comp cmp = Comp(str);
if (cpm(salary[i], 9000))
{
cout << "wow";
}
You'd have to "hack" in this required eval! ;) i.e.
template <typename T>
bool eval_op(const string& op, const T& lhs, const T& rhs)
{
switch(op.size())
{
case 2:
{
switch(op[1])
{
case '=':
{
switch(op[0])
{
case '=': return lhs == rhs;
case '!': return lhs != rhs;
case '>': return lhs >= rhs;
case '<': return lhs <= rhs;
}
}
default: throw("crazy fool!");
};
}
case 1:
{
switch(op[0])
{
case '>': return lhs > rhs;
case '<': return lhs < rhs;
default: throw ("crazy fool!");
}
}
default: throw ("crazy fool!");
}
return false;
}
DISCLAIMER: I've not tested this... but it's an idea...
In this particular situation an if-else branch is your simplest solution. This is simply because there are only so many comparison alternatives, and you can be sure none others will ever exist. In essence your code should be along the lines of
if( in == "==" )
cond = salary[i] == 9000;
else if( in == "!=" )
cond = salary[i] != 9000;
// ...
else
// throw, return -1, raise a flag or burst out in laughter
This is in fact safer than a dynamic eval() because here you sanitize the input. You make sure there is no malicious code in there, along the lines of a Little Bobby Tables attack.
Granted, you could use polymorphism here, but the point of polymorphism is support open-ended type alternatives. When you wish to add a case, polymorphism allows you to do that with ease. But you'd need to do some work to get foundations up, and here there are exactly 6 comparison alternatives. Or 7, if you want to add support for an arbitrary predicate.