I can clearly do something like this:
for(int i = 0; i < 10000; i++)
testIteration();
But is there any std functions which does similar thing in one line? Something like that:
std::repeat(10000, testIteration);
In the proposed standard for C++20 there is an example for iota_view:
for (int i : iota_view{1, 10})
cout << i << ' '; // prints: 1 2 3 4 5 6 7 8 9
But for now, range-v3 library can be used:
for (int _ : view::iota{0, 10})
testIteration(); // calls testIteration 10 times.
I personally like to use a small helper function to do this.
template <typename F>
void repeat(size_t n, F f) {
while (n--) f();
}
int main() {
repeat(1000, [&] {
testIteration();
});
}
This avoids having to spell out the name of a variable. I prefer using view::iota when I need a name though.
That being said, I'm told this is confusing to read, and everyone can read a for loop, so that's probably the way to go. (Unless the function is put in std:: of course).
But is there any std functions which does similar thing in one line?
No, there is no algorithm in the standard library to do this (at least nothing that would not require to write useless boilerplate). As others already mentioned a loop is the most readable and least obfuscated way to do "something" n-times.
That being said, if you take it as an exercise to get a more terse syntax, you could write this:
#include <iostream>
struct my_counter {
int stop;
struct iterator {
int count;
iterator& operator++() { ++count; return *this; }
int operator*() { return count;}
bool operator!=(const iterator& other) { return count != other.count; }
};
iterator begin() { return {0}; }
iterator end() { return {stop};}
};
void print() { std::cout << "x"; }
int main() {
for (auto x : my_counter{5}) print();
}
However, I would strongly advise against using something like that. Everybody knows how a loop works and what it does. Being used to for loops you can read a for loop in a blink, while anything else is uncommon, surprising and obfuscating, unless there is a standard algorithm of course (though I doubt that an algorithm for this particular case would be of great use). Why reinvent the wheel when you can use a loop?
I know this isn't providing anything new from the above answers except that perhaps that my solution is very short. To repeat code 2 times I use a loop like the following:
for (auto _{2}; _--;) { /* this code gets repeated twice */ }
I think using the prefix operator would be less clear since to repeat code twice the loop would need to be:
for (auto _{3}; --_;) { /* this code gets repeated twice */ }
Parentheses would also of course work instead of braces, i.e.:
for (auto _(2); _--) {}
Just for a reference, there is std::generate and std::generate_n which can be used, but only for array initialization by doing something like this:
int i = 0;
std::generate_n(myArray, 10000, [&]() -> int { return i++; });
What about simply defining a macro?
#define FOR(N, foo, ...) for (int _i = 0; _i < N; _i++) foo(__VA_ARGS__);
For eg.
#include <iostream>
#define FOR(N, foo, ...) for (int _i = 0; _i < N; _i++) foo(__VA_ARGS__);
void bar(int a, int b)
{
std::cout << "hello " << a+b << std::endl;
}
int main()
{
FOR(5, bar, 12, 6);
return 0;
}
Output:
hello 18
hello 18
hello 18
hello 18
hello 18
so you have a collection and you want to see if NONE of the items in it pass a test. doing the if ANY pass test is easy, and would look something like this:
for (int i = 0; i < collectionSize; i++)
{
if(ItemPasses(collection[i]))
{
// do code for if any pass
break;
}
}
but to do the opposite, if NONE pass test, I cant think of a truly neat way to do it, here are the ways I can come up with:
// nice to look at but uses an unecessary variable 'anItemPassed'
bool anItemPassed = false;
for (int i = 0; i < collectionSize; i++)
{
if(ItemPasses(collection[i]))
{
anItemPassed = true;
break;
}
}
if (!anItemPassed)
{
//...
}
//---------------------------------------------------------------------------------
// as efficient as possible but uses gotos.. nobody likes gotos.. lable stuff really isnt that neat.
for (int i = 0; i < collectionSize; i++)
{
if (ItemPasses(collection[i]))
{
goto ItemPassed;
}
}
//...
ItemPassed: { }
//-------------------------------------------------------------------------
// as efficient as possible and doesnt use the rarely used (and usually poorly supported in IDEs) goto/lable stuff, but doesnt use any nice loop construct, does it all manually
int i = 0;
for (; ; )
{
if (i >= collectionSize)
{
//...
break;
}
if (ItemPasses(collection[i]))
{
break;
}
i++;
}
I dont really like any of those, I've always wondered why there was never a construct like:
for (int i = 0; i < collectionSize; i++)
{
if (ItemPasses(collection[i]))
{
break;
}
}
finally //executed if the loop terminates normally, not via breaks.
{
//...
}
so in short my question is: Is there are truly neat way to do 'if none in collection' test? if not, is there a reason why the above wouldn't be a good language feature?
EDIT:
I instantly regret putting c++ in the tags. I know there are nice functions to do this, but assuming the boost libraries or whatnot, were also written in c/c++ presumably they encountered the same problem I have. even if these functions are built in to the language, saying 'just call this function' isn't the answer I was looking for in this case.
so maybe I will focus on the last part of my question: Is there a reason why the above wouldn't be a good language feature?
in my view not having it would be like not having the 'else' keyword to go with 'if'
For C++ it's pretty trivial (C++11 with none_of, C++14 with the auto lambda)
bool noneExist = std::none_of(std::begin(collection), std::end(collection), [](auto &item){
return item.matchesCondition(); // any evaluation can go here, or you could just supply an existing functor instead of a lambda
});
I assign to a bool here, but you could as easily wrap it in an if statement (this assumes an existing function or functor object named MatchCondition, a lambda would work, but that's a lot to read in an if condition):
if(std::none_of(std::begin(collection), std::end(collection), MatchCondition)){
//run your "if none of the above matched" code here.
}
And the old C++98 method for completion:
if(std::find_if(collection.begin(), collection.end(), MatchCondition) == collection.end()){
//run your "if none of the above matched" code here.
}
"Truly neat" sounds a bit opinion based but here are a few options:
#include <iostream>
#include <algorithm>
#include <vector>
bool itemPasses(int i) {
return i > 10;
}
void printIfNonePass1(const std::vector<int>& collection) {
if (std::none_of(collection.cbegin(), collection.cend(), itemPasses))
std::cout << "None pass\n";
}
void printIfNonePass2(const std::vector<int>& collection) {
auto iter = collection.cbegin();
for(; iter != collection.cend(); ++iter) {
if (itemPasses(*iter))
break;
}
if (iter == collection.cend())
std::cout << "None pass\n";
}
void printIfNonePass3(const std::vector<int>& collection) {
size_t i = 0;
for(; i != collection.size(); ++i) {
if (itemPasses(collection[i]))
break;
}
if (i == collection.size())
std::cout << "None pass\n";
}
bool checkIfNonePass(const std::vector<int>& collection) {
for(int item : collection) {
if (itemPasses(item))
return false;
}
return true;
}
void printIfNonePass4(const std::vector<int>& collection) {
if (checkIfNonePass(collection))
std::cout << "None pass\n";
}
int main() {
std::vector<int> collection{4,2,10,3};
printIfNonePass1(collection);
printIfNonePass2(collection);
printIfNonePass3(collection);
printIfNonePass4(collection);
}
I like to achieve this by performing the no-match scenario by comparing the iterator against the max.
int i;
for (i = 0; i < collectionSize; i++)
{
if (ItemPasses(collection[i]))
{
// do code for if any pass
break;
}
}
if (i == collectionSize)
{
// perform no-match operations
}
There is no need for c++14, or c++11. Something like this should do what you want.
if (find_if(collection.begin(), collection.end(), ItemPasses) == collection.end()) {
//code if none passes
}
edit: Adding c++11 solution as response to comment.
if (none_of(collection.begin(), collection.end(), ItemPasses)) {
//code if none passes
}
2:nd edit: Answer the question.
I think you are interested the internal realization of the algorithm but not applying standard algorithms.
Usually the loop is written the following way
CollectionType::size_type i = 0;
while ( i < collectionSize && !ItemPasses(collection[i]) ) ++i;
return ( i == collectionSize );
The same can be written with iterators
while ( first != last && !ItemPasses( *first ) ) ++first;
return ( first == last );
This approach can be applied also in C programs.
In my opinion, there is no orthgonality in control structures in many languages C included.
The need is obvious, and the language should simplify the work of the programmer, albeit no much will for work and/or change is done in that direction on the side of control structures.
In 1992, I had done a complete proposal and implementation of an orthogonal set of control structures, that could be used in many languages, and the construct you request was included, that is just to confirm the recurrency of the argument and the validity of the need.
The functions of C++ while permit an elegant solution, do not solve the need any way.
An alternative solution to what you already presented is to put the code you need inside the for construct. So the code would become as bellow while the function finalizationCode() should return false.
for (int i = 0; i < collectionSize ? true : finalizationCode(); i++)
It may be better to put the || construct instead of the if ( ? : ).
So in that case:
for(int i=0 ; i < collectionSize || finalizationCode() ;i++)
It is anyway guaranted that finalizationCode will be executed only when the condition i<collectionSize
is false.
I have the following Python snippet that I would like to reproduce using C++:
from itertools import count, imap
source = count(1)
pipe1 = imap(lambda x: 2 * x, source)
pipe2 = imap(lambda x: x + 1, pipe1)
sink = imap(lambda x: 3 * x, pipe2)
for i in sink:
print i
I've heard of Boost Phoenix, but I couldn't find an example of a lazy transform behaving in the same way as Python's imap.
Edit: to clarify my question, the idea is not only to apply functions in sequence using a for, but rather to be able to use algorithms like std::transform on infinite generators. The way the functions are composed (in a more functional language like dialect) is also important, as the next step is function composition.
Update: thanks bradgonesurfing, David Brown, and Xeo for the amazing answers! I chose Xeo's because it's the most concise and it gets me right where I wanted to be, but David's was very important into getting the concepts through. Also, bradgonesurfing's tipped Boost::Range :).
Employing Boost.Range:
int main(){
auto map = boost::adaptors::transformed; // shorten the name
auto sink = generate(1) | map([](int x){ return 2*x; })
| map([](int x){ return x+1; })
| map([](int x){ return 3*x; });
for(auto i : sink)
std::cout << i << "\n";
}
Live example including the generate function.
I think the most idiomatic way to do this in C++ is with iterators. Here is a basic iterator class that takes an iterator and applies a function to its result:
template<class Iterator, class Function>
class LazyIterMap
{
private:
Iterator i;
Function f;
public:
LazyIterMap(Iterator i, Function f) : i(i), f(f) {}
decltype(f(*i)) operator* () { return f(*i); }
void operator++ () { ++i; }
};
template<class Iterator, class Function>
LazyIterMap<Iterator, Function> makeLazyIterMap(Iterator i, Function f)
{
return LazyIterMap<Iterator, Function>(i, f);
}
This is just a basic example and is still incomplete as it has no way to check if you've reached the end of the iterable sequence.
Here's a recreation of your example python code (also defining a simple infinite counter class).
#include <iostream>
class Counter
{
public:
Counter (int start) : value(start) {}
int operator* () { return value; }
void operator++ () { ++value; }
private:
int value;
};
int main(int argc, char const *argv[])
{
Counter source(0);
auto pipe1 = makeLazyIterMap(source, [](int n) { return 2 * n; });
auto pipe2 = makeLazyIterMap(pipe1, [](int n) { return n + 1; });
auto sink = makeLazyIterMap(pipe2, [](int n) { return 3 * n; });
for (int i = 0; i < 10; ++i, ++sink)
{
std::cout << *sink << std::endl;
}
}
Apart from the class definitions (which are just reproducing what the python library functions do), the code is about as long as the python version.
I think the boost::rangex library is what you are looking for. It should work nicely with the new c++lambda syntax.
int pipe1(int val) {
return 2*val;
}
int pipe2(int val) {
return val+1;
}
int sink(int val) {
return val*3;
}
for(int i=0; i < SOME_MAX; ++i)
{
cout << sink(pipe2(pipe1(i))) << endl;
}
I know, it's not quite what you were expecting, but it certainly evaluates at the time you want it to, although not with an iterator iterface. A very related article is this:
Component programming in D
Edit 6/Nov/12:
An alternative, still sticking to bare C++, is to use function pointers and construct your own piping for the above functions (vector of function pointers from SO q: How can I store function pointer in vector?):
typedef std::vector<int (*)(int)> funcVec;
int runPipe(funcVec funcs, int sinkVal) {
int running = sinkVal;
for(funcVec::iterator it = funcs.begin(); it != funcs.end(); ++it) {
running = (*(*it))(running); // not sure of the braces and asterisks here
}
return running;
}
This is intended to run through all the functions in a vector of such and return the resulting value. Then you can:
funcVec funcs;
funcs.pushback(&pipe1);
funcs.pushback(&pipe2);
funcs.pushback(&sink);
for(int i=0; i < SOME_MAX; ++i)
{
cout << runPipe(funcs, i) << endl;
}
Of course you could also construct a wrapper for that via a struct (I would use a closure if C++ did them...):
struct pipeWork {
funcVec funcs;
int run(int i);
};
int pipeWork::run(int i) {
//... guts as runPipe, or keep it separate and call:
return runPipe(funcs, i);
}
// later...
pipeWork kitchen;
kitchen.funcs = someFuncs;
int (*foo) = &kitchen.run();
cout << foo(5) << endl;
Or something like that. Caveat: No idea what this will do if the pointers are passed between threads.
Extra caveat: If you want to do this with varying function interfaces, you will end up having to have a load of void *(void *)(void *) functions so that they can take whatever and emit whatever, or lots of templating to fix the kind of pipe you have. I suppose ideally you'd construct different kinds of pipe for different interfaces between functions, so that a | b | c works even when they are passing different types between them. But I'm going to guess that that's largely what the Boost stuff is doing.
Depending on the simplicity of the functions :
#define pipe1(x) 2*x
#define pipe2(x) pipe1(x)+1
#define sink(x) pipe2(x)*3
int j = 1
while( ++j > 0 )
{
std::cout << sink(j) << std::endl;
}
Compiling the following code gives the error message: type illegal.
int main()
{
// Compilation error - switch expression of type illegal
switch(std::string("raj"))
{
case"sda":
}
}
You cannot use string in either switch or case. Why? Is there any solution that works nicely to support logic similar to switch on strings?
The reason why has to do with the type system. C/C++ doesn't really support strings as a type. It does support the idea of a constant char array but it doesn't really fully understand the notion of a string.
In order to generate the code for a switch statement the compiler must understand what it means for two values to be equal. For items like ints and enums, this is a trivial bit comparison. But how should the compiler compare 2 string values? Case sensitive, insensitive, culture aware, etc ... Without a full awareness of a string this cannot be accurately answered.
Additionally, C/C++ switch statements are typically generated as branch tables. It's not nearly as easy to generate a branch table for a string style switch.
As mentioned previously, compilers like to build lookup tables that optimize switch statements to near O(1) timing whenever possible. Combine this with the fact that the C++ Language doesn't have a string type - std::string is part of the Standard Library which is not part of the Language per se.
I will offer an alternative that you might want to consider, I've used it in the past to good effect. Instead of switching over the string itself, switch over the result of a hash function that uses the string as input. Your code will be almost as clear as switching over the string if you are using a predetermined set of strings:
enum string_code {
eFred,
eBarney,
eWilma,
eBetty,
...
};
string_code hashit (std::string const& inString) {
if (inString == "Fred") return eFred;
if (inString == "Barney") return eBarney;
...
}
void foo() {
switch (hashit(stringValue)) {
case eFred:
...
case eBarney:
...
}
}
There are a bunch of obvious optimizations that pretty much follow what the C compiler would do with a switch statement... funny how that happens.
C++
constexpr hash function:
constexpr unsigned int hash(const char *s, int off = 0) {
return !s[off] ? 5381 : (hash(s, off+1)*33) ^ s[off];
}
switch( hash(str) ){
case hash("one") : // do something
case hash("two") : // do something
}
Update:
The example above is C++11. There constexpr function must be with single statement. This was relaxed in next C++ versions.
In C++14 and C++17 you can use following hash function:
constexpr uint32_t hash(const char* data, size_t const size) noexcept{
uint32_t hash = 5381;
for(const char *c = data; c < data + size; ++c)
hash = ((hash << 5) + hash) + (unsigned char) *c;
return hash;
}
Also C++17 have std::string_view, so you can use it instead of const char *.
In C++20, you can try using consteval.
C++ 11 update of apparently not #MarmouCorp above but http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4067/Switch-on-Strings-in-C.htm
Uses two maps to convert between the strings and the class enum (better than plain enum because its values are scoped inside it, and reverse lookup for nice error messages).
The use of static in the codeguru code is possible with compiler support for initializer lists which means VS 2013 plus. gcc 4.8.1 was ok with it, not sure how much farther back it would be compatible.
/// <summary>
/// Enum for String values we want to switch on
/// </summary>
enum class TestType
{
SetType,
GetType
};
/// <summary>
/// Map from strings to enum values
/// </summary>
std::map<std::string, TestType> MnCTest::s_mapStringToTestType =
{
{ "setType", TestType::SetType },
{ "getType", TestType::GetType }
};
/// <summary>
/// Map from enum values to strings
/// </summary>
std::map<TestType, std::string> MnCTest::s_mapTestTypeToString
{
{TestType::SetType, "setType"},
{TestType::GetType, "getType"},
};
...
std::string someString = "setType";
TestType testType = s_mapStringToTestType[someString];
switch (testType)
{
case TestType::SetType:
break;
case TestType::GetType:
break;
default:
LogError("Unknown TestType ", s_mapTestTypeToString[testType]);
}
The problem is that for reasons of optimization the switch statement in C++ does not work on anything but primitive types, and you can only compare them with compile time constants.
Presumably the reason for the restriction is that the compiler is able to apply some form of optimization compiling the code down to one cmp instruction and a goto where the address is computed based on the value of the argument at runtime. Since branching and and loops don't play nicely with modern CPUs, this can be an important optimization.
To go around this, I am afraid you will have to resort to if statements.
std::map + C++11 lambdas pattern without enums
unordered_map for the potential amortized O(1): What is the best way to use a HashMap in C++?
#include <functional>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
int main() {
int result;
const std::unordered_map<std::string,std::function<void()>> m{
{"one", [&](){ result = 1; }},
{"two", [&](){ result = 2; }},
{"three", [&](){ result = 3; }},
};
const auto end = m.end();
std::vector<std::string> strings{"one", "two", "three", "foobar"};
for (const auto& s : strings) {
auto it = m.find(s);
if (it != end) {
it->second();
} else {
result = -1;
}
std::cout << s << " " << result << std::endl;
}
}
Output:
one 1
two 2
three 3
foobar -1
Usage inside methods with static
To use this pattern efficiently inside classes, initialize the lambda map statically, or else you pay O(n) every time to build it from scratch.
Here we can get away with the {} initialization of a static method variable: Static variables in class methods , but we could also use the methods described at: static constructors in C++? I need to initialize private static objects
It was necessary to transform the lambda context capture [&] into an argument, or that would have been undefined: const static auto lambda used with capture by reference
Example that produces the same output as above:
#include <functional>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
class RangeSwitch {
public:
void method(std::string key, int &result) {
static const std::unordered_map<std::string,std::function<void(int&)>> m{
{"one", [](int& result){ result = 1; }},
{"two", [](int& result){ result = 2; }},
{"three", [](int& result){ result = 3; }},
};
static const auto end = m.end();
auto it = m.find(key);
if (it != end) {
it->second(result);
} else {
result = -1;
}
}
};
int main() {
RangeSwitch rangeSwitch;
int result;
std::vector<std::string> strings{"one", "two", "three", "foobar"};
for (const auto& s : strings) {
rangeSwitch.method(s, result);
std::cout << s << " " << result << std::endl;
}
}
To add a variation using the simplest container possible (no need for an ordered map)... I wouldn't bother with an enum--just put the container definition immediately before the switch so it'll be easy to see which number represents which case.
This does a hashed lookup in the unordered_map and uses the associated int to drive the switch statement. Should be quite fast. Note that at is used instead of [], as I've made that container const. Using [] can be dangerous--if the string isn't in the map, you'll create a new mapping and may end up with undefined results or a continuously growing map.
Note that the at() function will throw an exception if the string isn't in the map. So you may want to test first using count().
const static std::unordered_map<std::string,int> string_to_case{
{"raj",1},
{"ben",2}
};
switch(string_to_case.at("raj")) {
case 1: // this is the "raj" case
break;
case 2: // this is the "ben" case
break;
}
The version with a test for an undefined string follows:
const static std::unordered_map<std::string,int> string_to_case{
{"raj",1},
{"ben",2}
};
// in C++20, you can replace .count with .contains
switch(string_to_case.count("raj") ? string_to_case.at("raj") : 0) {
case 1: // this is the "raj" case
break;
case 2: // this is the "ben" case
break;
case 0: //this is for the undefined case
}
In C++ and C switches only work on integer types. Use an if else ladder instead. C++ could obviously have implemented some sort of swich statement for strings - I guess nobody thought it worthwhile, and I agree with them.
Why not? You can use switch implementation with equivalent syntax and same semantics.
The C language does not have objects and strings objects at all, but
strings in C is null terminated strings referenced by pointer.
The C++ language have possibility to make overload functions for
objects comparision or checking objects equalities.
As C as C++ is enough flexible to have such switch for strings for C
language and for objects of any type that support comparaison or check
equality for C++ language. And modern C++11 allow to have this switch
implementation enough effective.
Your code will be like this:
std::string name = "Alice";
std::string gender = "boy";
std::string role;
SWITCH(name)
CASE("Alice") FALL
CASE("Carol") gender = "girl"; FALL
CASE("Bob") FALL
CASE("Dave") role = "participant"; BREAK
CASE("Mallory") FALL
CASE("Trudy") role = "attacker"; BREAK
CASE("Peggy") gender = "girl"; FALL
CASE("Victor") role = "verifier"; BREAK
DEFAULT role = "other";
END
// the role will be: "participant"
// the gender will be: "girl"
It is possible to use more complicated types for example std::pairs or any structs or classes that support equality operations (or comarisions for quick mode).
Features
any type of data which support comparisions or checking equality
possibility to build cascading nested switch statemens.
possibility to break or fall through case statements
possibility to use non constatnt case expressions
possible to enable quick static/dynamic mode with tree searching (for C++11)
Sintax differences with language switch is
uppercase keywords
need parentheses for CASE statement
semicolon ';' at end of statements is not allowed
colon ':' at CASE statement is not allowed
need one of BREAK or FALL keyword at end of CASE statement
For C++97 language used linear search.
For C++11 and more modern possible to use quick mode wuth tree search where return statement in CASE becoming not allowed.
The C language implementation exists where char* type and zero-terminated string comparisions is used.
Read more about this switch implementation.
I think the reason is that in C strings are not primitive types, as tomjen said, think in a string as a char array, so you can not do things like:
switch (char[]) { // ...
switch (int[]) { // ...
In c++ strings are not first class citizens. The string operations are done through standard library. I think, that is the reason. Also, C++ uses branch table optimization to optimize the switch case statements. Have a look at the link.
http://en.wikipedia.org/wiki/Switch_statement
Late to the party, here's a solution I came up with some time ago, which completely abides to the requested syntax.
#include <uberswitch/uberswitch.hpp>
int main()
{
uswitch (std::string("raj"))
{
ucase ("sda"): /* ... */ break; //notice the parenthesis around the value.
}
}
Here's the code: https://github.com/falemagn/uberswitch
You could put the strings in an array and use a constexpr to convert them to indices at compile time.
constexpr const char* arr[] = { "bar", "foo" };
constexpr int index(const char* str) { /*...*/ }
do_something(std::string str)
{
switch(quick_index(str))
{
case index("bar"):
// ...
break;
case index("foo"):
// ...
break;
case -1:
default:
// ...
break;
}
For quick_index, which doesn't have to be constexpr, you could e.g. use an unordered_map to do it O(1) at runtime. (Or sort the array and use binary search, see here for an example.)
Here's a full example for C++11, with a simple custom constexpr string comparer. Duplicate cases and cases not in the array (index gives -1) will be detected at compile time. Missing cases are obviously not detected. Later C++ versions have more flexible constexpr expressions, allowing for simpler code.
#include <iostream>
#include <algorithm>
#include <unordered_map>
constexpr const char* arr[] = { "bar", "foo", "foobar" };
constexpr int cmp(const char* str1, const char* str2)
{
return *str1 == *str2 && (!*str1 || cmp(str1+1, str2+1));
}
constexpr int index(const char* str, int pos=0)
{
return pos == sizeof(arr)/sizeof(arr[0]) ? -1 : cmp(str, arr[pos]) ? pos : index(str,pos+1);
}
int main()
{
// initialize hash table once
std::unordered_map<std::string,int> lookup;
int i = 0;
for(auto s : arr) lookup[s] = i++;
auto quick_index = [&](std::string& s)
{ auto it = lookup.find(s); return it == lookup.end() ? -1 : it->second; };
// usage in code
std::string str = "bar";
switch(quick_index(str))
{
case index("bar"):
std::cout << "bartender" << std::endl;
break;
case index("foo"):
std::cout << "fighter" << std::endl;
break;
case index("foobar"):
std::cout << "fighter bartender" << std::endl;
break;
case -1:
default:
std::cout << "moo" << std::endl;
break;
}
}
hare's comment to Nick's solution is really cool. here the complete code example (in C++11):
constexpr uint32_t hash(const std::string& s) noexcept
{
uint32_t hash = 5381;
for (const auto& c : s)
hash = ((hash << 5) + hash) + (unsigned char)c;
return hash;
}
constexpr inline uint32_t operator"" _(char const* p, size_t) { return hash(p); }
std::string s = "raj";
switch (hash(s)) {
case "sda"_:
// do_something();
break;
default:
break;
}
In C++ you can only use a switch statement on int and char
cout << "\nEnter word to select your choice\n";
cout << "ex to exit program (0)\n";
cout << "m to set month(1)\n";
cout << "y to set year(2)\n";
cout << "rm to return the month(4)\n";
cout << "ry to return year(5)\n";
cout << "pc to print the calendar for a month(6)\n";
cout << "fdc to print the first day of the month(1)\n";
cin >> c;
cout << endl;
a = c.compare("ex") ?c.compare("m") ?c.compare("y") ? c.compare("rm")?c.compare("ry") ? c.compare("pc") ? c.compare("fdc") ? 7 : 6 : 5 : 4 : 3 : 2 : 1 : 0;
switch (a)
{
case 0:
return 1;
case 1: ///m
{
cout << "enter month\n";
cin >> c;
cout << endl;
myCalendar.setMonth(c);
break;
}
case 2:
cout << "Enter year(yyyy)\n";
cin >> y;
cout << endl;
myCalendar.setYear(y);
break;
case 3:
myCalendar.getMonth();
break;
case 4:
myCalendar.getYear();
case 5:
cout << "Enter month and year\n";
cin >> c >> y;
cout << endl;
myCalendar.almanaq(c,y);
break;
case 6:
break;
}
More functional workaround to the switch problem:
class APIHandlerImpl
{
// define map of "cases"
std::map<string, std::function<void(server*, websocketpp::connection_hdl, string)>> in_events;
public:
APIHandlerImpl()
{
// bind handler method in constructor
in_events["/hello"] = std::bind(&APIHandlerImpl::handleHello, this, _1, _2, _3);
in_events["/bye"] = std::bind(&APIHandlerImpl::handleBye, this, _1, _2, _3);
}
void onEvent(string event = "/hello", string data = "{}")
{
// execute event based on incomming event
in_events[event](s, hdl, data);
}
void APIHandlerImpl::handleHello(server* s, websocketpp::connection_hdl hdl, string data)
{
// ...
}
void APIHandlerImpl::handleBye(server* s, websocketpp::connection_hdl hdl, string data)
{
// ...
}
}
You can use switch on strings.
What you need is table of strings, check every string
char** strings[4] = {"Banana", "Watermelon", "Apple", "Orange"};
unsigned get_case_string(char* str, char** _strings, unsigned n)
{
while(n)
{
n--
if(strcmp(str, _strings[n]) == 0) return n;
}
return 0;
}
unsigned index = get_case_string("Banana", strings, 4);
switch(index)
{
case 1: break;/*Found string `Banana`*/
default: /*No string*/
}
You can't use string in switch case.Only int & char are allowed. Instead you can try enum for representing the string and use it in the switch case block like
enum MyString(raj,taj,aaj);
Use it int the swich case statement.
That's because C++ turns switches into jump tables. It performs a trivial operation on the input data and jumps to the proper address without comparing. Since a string is not a number, but an array of numbers, C++ cannot create a jump table from it.
movf INDEX,W ; move the index value into the W (working) register from memory
addwf PCL,F ; add it to the program counter. each PIC instruction is one byte
; so there is no need to perform any multiplication.
; Most architectures will transform the index in some way before
; adding it to the program counter
table ; the branch table begins here with this label
goto index_zero ; each of these goto instructions is an unconditional branch
goto index_one ; of code
goto index_two
goto index_three
index_zero
; code is added here to perform whatever action is required when INDEX = zero
return
index_one
...
(code from wikipedia https://en.wikipedia.org/wiki/Branch_table)
in many cases you can avid extra work by pulling the first char from the string and switching on that. may end up having to do a nested switch on charat(1) if your cases start with the same value. anyone reading your code would appreciate a hint though because most would prob just if-else-if
Switches only work with integral types (int, char, bool, etc.). Why not use a map to pair a string with a number and then use that number with the switch?