Firstly,I want to inform you that my overall/main target is to execute certain functions using their function name(string) as an argument,I defined a function as below:
(I want to generate a unique number for each string data that I inserted as argument to a function)
#include <iostream>
#include <string>
#include <hash_set>
using namespace std;
void Func_Execution(string &s){
int k=stdext::hash_value(s);
#if(_MSC_VER ==1500)
switch (k)
{
case -336300864: GETBATTERYCALLSIGNS();
break;
case -1859542241:GETGUNIDS();
break;
case 323320073:Foo(); // here int k=323320073 for string s="Foo"
break;
case 478877555:Bar();
break;
defalut :Exit();
break;
}
#endif
}
Here I call Func_Execution function as below:
void main(){
string s="Foo";
Func_Execution(s);
}
I want to know that is there any efficient(considering perfomance/time consuming) and effective mechanism to generate a unique numerical value for certain string(character pattern) rather than using stdext::hash_value() function?(Also notice I want to implement switch-case too)
Have you considered something like
#include <functional>
#include <iostream>
#include <unordered_map>
#include <string>
using std::cout;
using std::endl;
using std::function;
using std::string;
using std::unordered_map;
class Registry {
public:
static void Execute(const string& function) {
if (functions_.find(function) != functions_.end()) {
functions_[function]();
}
}
static int Register(const string& function_name, function<void()> f) {
functions_.emplace(function_name, f);
return functions_.size();
}
static void Dump() {
for (auto& i : functions_) {
cout << i.first << endl;
}
}
private:
Registry() {};
static unordered_map<string, function<void()>> functions_;
};
unordered_map<string, function<void()>> Registry::functions_;
#define REGISTER_FUNCTION(F) \
namespace { \
const int REGISTERED__##F = Registry::Register(#F, &F); \
}
void foo() {
cout << "foo" << endl;
}
REGISTER_FUNCTION(foo);
void bar() {
cout << "bar" << endl;
}
REGISTER_FUNCTION(bar);
int main() {
Registry::Execute("foo");
Registry::Execute("foo");
Registry::Execute("unknown");
Registry::Dump();
return 0;
}
It should serve well for your use case. I just hacked it together, there's probably a bug somewhere, but it compiles and runs (c++11).
Don't use hash_value() for fingerprinting (which is what you are describing). If you really know all your possible strings ahead of time, use your own perfect hash function and then measure the results to see if it is worth it.
Related
I have the following code:
#include<iostream>
using namespace std;
void saludo();
void despedida();
int main(){
void (*Ptr_Funciones[2])() = {saludo, despedida};
(Ptr_Funciones[0])();
(Ptr_Funciones[1])();
return 0;
}
void saludo(){
cout<<"\nHola mundo";
}
void despedida(){
cout<<"\nAdios mundo"<<endl<<endl;
}
Based on this, a few questions were generated which I investigated before asking but did not fully understand.
The questions are:
How do I make an array of functions, if they are of a different type?
I know that in C ++ this notation is used for undetermined parameters: (type var ...) The
thing is, I don't know how to interact with them inside the function.
If questions 1 and 2 are possible, can these points be combined when creating function
arrays?
I really have investigated. But I can't find much information, and the little I did find I didn't understand very well. I hope you can collaborate with me.
Thank you very much.
How do I make an array of functions, if they are of a different type?
You can, but you don't want to. It doesn't make semantic sense. An array is a collection of the same kind of thing. If you find that you need to make a collection of different kinds of things, there are several data structures at your disposal.
I know that in C++ this notation is used for undetermined parameters: (type var ...) The thing is, I don't know how to interact with them inside the function.
Here's how you can use the syntax you mention. They're called variadic functions.
If questions 1 and 2 are possible, can these points be combined when creating function arrays?
Erm, I can't imagine why/when a combination of these two would be needed, but out of intellectual curiosity, awayyy we go...
A modified version of the code from the reference link above that kinda does what you want (i've used a map instead of an array, cuz why not):
#include <iostream>
#include <cstdarg>
#include <unordered_map>
template<typename T>
using fooptr = void (*) (T *t...);
struct A {
const char *fmt;
A(const char *s) :fmt{s} {}
};
struct B : public A {
B(const char *s) : A{s} {}
};
void simple_printf(A *a...)
{
va_list args;
auto fmt = a->fmt;
va_start(args, a);
while (*fmt != '\0') {
if (*fmt == 'd') {
int i = va_arg(args, int);
std::cout << i << '\n';
} else if (*fmt == 'c') {
// note automatic conversion to integral type
int c = va_arg(args, int);
std::cout << static_cast<char>(c) << '\n';
} else if (*fmt == 'f') {
double d = va_arg(args, double);
std::cout << d << '\n';
}
++fmt;
}
va_end(args);
}
int main()
{
A a{"dcff"};
B b{"dcfff"};
std::unordered_map<size_t, fooptr<struct A>> index;
index[1] = simple_printf;
index[5] = simple_printf;
index[1](&a, 3, 'a', 1.999, 42.5);
index[5](&b, 4, 'b', 2.999, 52.5, 100.5);
}
This still really doesn't do what you wanted (i.e., give us the ability to choose from different functions during runtime). Bonus points if you understand why that's the case and/or how to fix it to do what you want.
Use a type alias to make things readable:
Live On Coliru
using Signature = void();
Signature* Ptr_Funciones[] = { saludo, despedida };
Prints
Hola mundo
Adios mundo
More flexible:
You can also use a vector:
Live On Coliru
#include <iostream>
#include <vector>
using namespace std;
void saludo() { cout << "\nHola mundo"; }
void despedida() { cout << "\nAdios mundo" << endl << endl; }
int main() {
vector Ptr_Funciones = { saludo, despedida };
Ptr_Funciones.front()();
Ptr_Funciones.back()();
}
Prints the same.
More Flexibility: Calleables of Different Types
To bind different types of functions, type-erasure should be used. std::function helps:
Live On Coliru
#include <iostream>
#include <functional>
#include <vector>
using namespace std;
void saludo(int value) { cout << "\nHola mundo (" << value << ")"; }
std::string despedida() { cout << "\nAdios mundo" << endl << endl; return "done"; }
int main() {
vector<function<void()>>
Ptr_Funciones {
bind(saludo, 42),
despedida
};
Ptr_Funciones.front()();
Ptr_Funciones.back()();
}
Prints
Hola mundo (42)
Adios mundo
Here is one solution that is possible, whether it fits your needs I'm not sure.
#include <Windows.h>
#include <iostream>
void saludo()
{
std::cout << "\nHola mundo" << std::endl;;
}
void despedida()
{
std::cout << "\nAdios mundo" << std::endl;
}
void* fnPtrs[2];
typedef void* (VoidFunc)();
int main()
{
fnPtrs[0] = saludo;
fnPtrs[1] = despedida;
((VoidFunc*)fnPtrs[0])();
((VoidFunc*)fnPtrs[1])();
std::getchar();
return 0;
}
I'm looking for a way to store function pointers in a container like a vector. This is possible if all the functions have the same parameters but can I do if the functions have individually unique parameters?
#include <iostream>
#include <vector>
using namespace std;
void sayHi() {
cout << "Hi" << endl;
}
void sayNum(int num) {
cout << num << endl;
}
int main() {
vector<void(*)()> funcs; // vector of 0 argument functions
funcs.push_back(sayHi);
funcs.push_back(sayNum); // can't store sayNum because it takes arguments
}
Note that I can't use std::function or std::bind because VS2013 doesn't have them and I'd rather not use the boost library. The solution must be allow the possibility to iterate through the vector of function pointers and execute each one with some valid arguments.
Forgive my potential ignorance about how function pointers work, I'm very used to doing this sort of thing in Javascript in one statement :P
Made the mistake of not including as I couldn't see it mentioned in anybody's code examples but it's probably just me being bad at C++.
Not going to accept my own answer, but thought I'd post my code just in the interests of anybody who might find it useful.
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
typedef std::vector<std::function<void(void)>> f_list;
f_list f1;
void _sayHi();
void _sayNum(int num);
void sayHi() {
f1.push_back(
std::bind(&_sayHi)
);
}
void sayNum(int num) {
f1.push_back(
std::bind(&_sayNum, num)
);
}
void _sayHi() {
cout << "hi" << endl;
}
void _sayNum(int num) {
cout << num << endl;
}
int main() {
sayHi();
sayNum(5);
for (int i = 0; i < f1.size(); i++) {
f1.at(i)(); // will execute desired functions
}
}
VS 2103 has std::function, std::bind and lambdas. Simply use them.
#include <boost/ref.hpp>
//#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/mem_fn.hpp>
using namespace std;
using namespace boost::lambda;
class Base {
public:
Base () {}
bool toBeRemoved() const {
return true;
}
};
class status : public Base {
std::string name_;
bool ok_;
public:
status(const std::string& name):name_(name),ok_(true) {}
void break_it() {
ok_=false;
}
bool is_broken() const {
return ok_;
}
void report() const {
std::cout << name_ << " is " <<
(ok_ ? "working nominally":"terribly broken") << '\n';
}
std::string getStatus() const {
return ok_ ? "1" : "0";
}
};
class some_class {
public:
int test() {
std::vector<boost::shared_ptr<status> > s_statuses = getStatus(); //some func
std::set<string> s;
std::transform(s_statuses.begin(), s_statuses.end(), std::inserter(s, s.begin()), boost::lambda::bind(boost::mem_fn(&status::getStatus), boost::ref(*_1)));
// approach #2
// std::transform(s_statuses.begin(), s_statuses.end(), std::inserter(s, s.begin()), boost::lambda::bind(boost::mem_fn(&status::getStatus), boost::ref(*_1), _1));
// approach #3
// std::transform(s_statuses.begin(), s_statuses.end(), std::inserter(s, s.begin()), boost::bind(&status::getStatus), _1));
std::copy(s.begin(), s.end(), ostream_iterator<string>(std::cout, "-"));
std::cout << endl;
return 0;
}
}
For all the approaches above, I am getting the error "can call member function without object" on the line containing the bind call. I have tried using boost::lambda::bind and boost::bind as well. Though this way of using bind works if objects are defined, for example in main function. I assume I am making some silly mistake here, but I am not able to figure out why these all approaches working, or it could be the case that this is not the right way of doing at all.
Could someone please help me resolve this on how to properly use boost bind for non-static member of class which are stored in stl containers ?
Thanks,
You should just need to use boost::mem_fn. (Note, you could also use std::mem_fn if available.)
std::transform(s_statuses.begin(), s_statuses.end(), std::inserter(s, s.begin()), std::mem_fn(&status::getStatus));
I have a large series of functions that all look very similar: they take the same arguement type and return strings.
std::string f1(T arg);
std::string f2(T arg);
std::string f3(T arg);
std::string f4(T arg);
.
.
.
In a loop, they are used according to one of the variables inside the struct T. Currently to do this, I just have a large switch/case block in my code.
Is there any better coding style for doing this? The large block of code looks very weird.
I wish c++ could be like python and do eval("f" + str(i) + "(arg))"
The block is something like this:
std::string out = "";
switch (arg.tag){
case 1:
out += f1(arg);
break;
case 2:
out += f2(arg);
break;
.
.
.
}
for about 2 dozen cases
With C++11 you can do this fairly easily with std::function and a map:
#include <map>
#include <functional>
#include <string>
#include <iostream>
std::string f1(int) { return "f1"; }
std::string f2(int) { return "f2"; }
std::map<int, std::function<std::string(int)> > funcs = {
{1,f1},
{2,f2}
};
int main() {
std::cout << funcs[1](100) << "\n";
}
Without C++11 you'll want to either use Boost instead of std::function or roll your own type instead. You could use plain old function pointers but that would rule out some handy things (like std::bind/boost::bind, functor objects, lambda functions. You could also define a type hierarchy with an interface that your functions implement for example the following works in C++03 except for the way the map is initialised:
#include <map>
#include <functional>
#include <string>
#include <iostream>
std::string f1(int) { return "f1"; }
std::string f2(int) { return "f2"; }
std::map<int, std::string(*)(int)> funcs = {
std::make_pair(1,f1),
std::make_pair(2,f2)
};
int main() {
std::cout << funcs[1](100) << "\n";
}
or this which lets you write any kind of functor object you like:
#include <map>
#include <string>
#include <iostream>
struct thing {
virtual std::string operator()(int) const = 0;
};
struct f1 : thing {
std::string operator()(int) const { return "f1"; }
};
struct f2 : thing {
std::string operator()(int) const { return "f2"; }
};
// Note the leak - these never get deleted:
std::map<int, thing*> funcs = {
std::make_pair(1,new f1),
std::make_pair(2,new f2)
};
int main() {
std::cout << (*funcs[1])(100) << "\n";
}
One way to emulate the Eval() is to have a map. The key of the map would be the names of the functions, and the values would be the pointers to the corresponding functions.
In this case you will be able to call the functions needed with the map's operator[] by their name. This will somehow emulate the eval("f" + str(i) + "(arg))" behavior, though it may still not be the best solution for you.
#include <boost/bind.hpp>
#include <iostream>
using namespace std;
using boost::bind;
class A {
public:
void print(string &s) {
cout << s.c_str() << endl;
}
};
typedef void (*callback)();
class B {
public:
void set_callback(callback cb) {
m_cb = cb;
}
void do_callback() {
m_cb();
}
private:
callback m_cb;
};
void main() {
A a;
B b;
string s("message");
b.set_callback(bind(A::print, &a, s));
b.do_callback();
}
So what I'm trying to do is to have the print method of A stream "message" to cout when b's callback is activated. I'm getting an unexpected number of arguments error from msvc10. I'm sure this is super noob basic and I'm sorry in advance.
replace typedef void (*callback)(); with typedef boost::function<void()> callback;
A bound function doesn't produce an ordinary function, so you cannot just store it in a regular function pointer. However, boost::function is able to handle anything as long as it is callable with the correct signature, so that's what you want. It will work with a function pointer, or a functor created with bind.
After a few corrections to your code, I came up with this:
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>
// i prefer explicit namespaces, but that's a matter of preference
class A {
public:
// prefer const refs to regular refs unless you need to modify the argument!
void print(const std::string &s) {
// no need for .c_str() here, cout knows how to output a std::string just fine :-)
std::cout << s << std::endl;
}
};
// holds any arity 0 callable "thing" which returns void
typedef boost::function<void()> callback;
class B {
public:
void set_callback(callback cb) {
m_cb = cb;
}
void do_callback() {
m_cb();
}
private:
callback m_cb;
};
void regular_function() {
std::cout << "regular!" << std::endl;
}
// the return type for main is int, never anything else
// however, in c++, you may omit the "return 0;" from main (and only main)
// which will have the same effect as if you had a "return 0;" as the last line
// of main
int main() {
A a;
B b;
std::string s("message");
// you forget the "&" here before A::print!
b.set_callback(boost::bind(&A::print, &a, s));
b.do_callback();
// this will work for regular function pointers too, yay!
b.set_callback(regular_function);
b.do_callback();
}