C++ making a console: binding a function - c++

I am currently working on creating a console in c++. I have created a class to help link variables and functions in code to variables and functions in the console.
I currently have it set where if I have a variable in code, I can redefine it under the new class and it will be visible to the console. The variable in code still behaves the same as before.
Example:
float var = 1.0;
can be redefined as
ConsoleVar var("myVariable")<float> = 1.0;
var is the variable name in the code and myVariable is the name that you use to access it in the terminal
My question is:
How can I bind a function, or more specifically, detect the number and type of the arguments.
I know that I can template the ConsoleVar class to a void * type to store a function but is there a way for me to auto detect the return type, number of arguments and type of arguments? I am planning on shipping this in a library so I am going for ease of use. If this is possible, I would really like to know (I'll even do assembly if needed) otherwise I have some ideas on how to implement it.
EDIT: So I think that I have a solution but I have a question... Is it possible to pass a variable number of arguments to a function. Not like varargs.
For instance: I recieve 3 args from the command line, now I execute the function
func(arg[1], arg[2], arg[3])
Is it possible to send a variable number of arguments?

This pattern will do the job.
#include <typeinfo>
// Function with 0 parameters
template< typename Ret >
void examine_function( Ret (*func)() )
{
std::cout << typeinfo(Ret).name() << std::endl;
}
// Function with 1 parameters
template< typename Ret, typename Param1 >
void examine_function( Ret (*func)(Param1) )
{
std::cout << typeinfo(Ret).name() << std::endl;
std::cout << typeinfo(Param1).name() << std::endl;
}
// Function with 2 parameters
template< typename Ret, typename Param1, typename Param2 >
void examine_function( Ret (*func)(Param1, Param2) )
{
std::cout << typeinfo(Ret).name() << std::endl;
std::cout << typeinfo(Param1).name() << std::endl;
std::cout << typeinfo(Param2).name() << std::endl;
}

Related

Is there anyway that I can determine whether the construct function is exist?

#include <iostream>
template<typename _OutType, typename _InType>
struct ConvertClass
{
_OutType operator()(_InType src)
{
return _OutType(src);
}
};
class OutClass
{
public:
OutClass(std::string str)
{
std::cout << "construct function works well!" << std::endl;
}
};
int main()
{
ConvertClass<OutClass, int>()(20); // this is wrong, because the OutClass only have one construct which takes the std::string type parameter.
// ConvertClass<OutClass, std::string>()(std::string("Hello!"));
/*
if (...) // So I wonder if there is any way that we can know whether the construct function is exists or not before we call the OutClass(int i) function
{
std::cout << "there is no such construct function of OutClass to take that parameter type" << std::endl;
return -1;
}
else
{
std::cout << "construct function works well!" << std::endl;
return 0;
}
*/
}
My Problem:
I know the main function is definitely wrong for the OutClass don't have the construct function OutClass(string str).
I wonder if there is a way only to change the Comment 1 section, the template class to make this file be compiled and linked successfully.
My English is not good, hoping you guys don't mind!
Thank you !
to my knowledge there is not runtime checking if given class is constructible using argument of given type
as said in my previous answer you can resort to Concepts and check the types at compiletime, but if clause does not work at compile time
To me it looks like the best solution would be indeed making a template class out of OutClass, then you have a single class with serves diverse purposes, dependent on you needs
one more edit to your code, I see that you pass the _OutType and _InType to your template.
In the setting where we have the following class template
template<class srcType>
class OutType:{
srcType src;
public:
OutType(srcType src) : src(src) {std::cout << "constructor works well!" << std::endl;}
}
then while invoking the class ConvertClass:
auto val = ConvertClass<OutClass<std::string>, std::string>()(std::string("Hello!"));
and also this will work:
auto val = ConvertClass<OutClass<int>, int>(20);
however, since operator() is not a static method you need first to construct object of class ConvertClass
In c++20 or even in c++17 you can in fact check if OutClass is constructible from int:
so your if clause should look like this
if(std::is_constructible<OutClass, int>::value) {
std::cout << "all is well" << std::endl;
}else{
std::cout << "you can't construct OutClass from int" << std::endl;
}
you can make the the following class template from the OutClass
template<class SrcType>
class OutClass {
SrcType src;
public:
OutClass(SrcType src) : src(src) {}
}
then in your code
return OutType<InType>(src);
if you need to check what the classes passed as template arguments actually can do (if they are arithmetic or additive or copy constructible e.g.) use Concepts from the C++20 standard

Store a function with arbitrary arguments and placeholders in a class and call it later

So I am creating a type of event handler and I am in the process of writing an "Event Listener Wrapper", if you will.
The basic idea is this:
When you want to subscribe to an event, you create a function that should be called when the event fires. <-- already have that done (kinda, I'll explain)
You put this listener function into a wrapper to pass the function onto the dispatcher.
The dispatcher gets an event, finds the wrapper for you listener, and calls the underlying function with the parameter values set by the event.
I already have something working so long as the listeners all only accept one argument of my EventBase class. Then I have to type cast that into the proper event that the listener is passed.
What I want instead is for my listener functions to have "any" type of arguments, and store the function in a way that lets me call it with any arguments I want depending on the event fired. Each listener function would only ever receive one type of event, or the event it's self. This would allow me to not have to type cast each event in every listener, but instead the correct event would be passed.
I found a bit of code for this wrapper that is almost perfect, with a few minor issues that I can't seem to fix. I'll explain below.
Code by #hmjd:
#include <iostream>
#include <string>
#include <functional>
#include <memory>
void myFunc1(int arg1, float arg2)
{
std::cout << arg1 << ", " << arg2 << '\n';
}
void myFunc2(const char *arg1)
{
std::cout << arg1 << '\n';
}
class DelayedCaller
{
public:
template <typename TFunction, typename... TArgs>
static std::unique_ptr<DelayedCaller> setup(TFunction&& a_func,
TArgs&&... a_args)
{
return std::unique_ptr<DelayedCaller>(new DelayedCaller(
std::bind(std::forward<TFunction>(a_func),
std::forward<TArgs>(a_args)...)));
}
void call() const { func_(); }
private:
using func_type = std::function<void()>;
DelayedCaller(func_type&& a_ft) : func_(std::forward<func_type>(a_ft)) {}
func_type func_;
};
int main()
{
auto caller1(DelayedCaller::setup(&myFunc1, 123, 45.6));
auto caller2(DelayedCaller::setup(&myFunc2, "A string"));
caller1->call();
caller2->call();
return 0;
}
The first thing I did here was I had to replace std::unique_ptr with std::shared_ptr. Not sure why really. This almost works. In my use case, I need to store a method function (meaning bind needs to be passed the containing method object?), and at the time of storing the function I don't know what the argument value will be, thats up for the event to decide. So my adjustment is as follows:
class DelayedCaller
{
public:
template <typename TFunction, typename TClass>
static std::shared_ptr<DelayedCaller> setup(TFunction&& a_func,
TClass && a_class)
{
auto func = std::bind(std::forward<TFunction>(a_func),
std::forward<TClass>(a_class),
std::placeholders::_1);
return std::shared_ptr<DelayedCaller>(new DelayedCaller(func));
}
template <typename T>
void call( T v ) const { func_(v); }
private:
using func_type = std::function<void( )>;
DelayedCaller(func_type&& a_ft) : func_(std::forward<func_type>(a_ft)) {}
func_type func_;
};
For the sake of testing, I removed the parameter pack and replaced it with a direct parameter to the class object holding the function. I also gave the bind a placeholder for 1 argument (ideally replaced by the void call() function later).
It's created like this:
eventManager->subscribe(EventDemo::descriptor, DelayedCaller::setup(
&AppBaseLogic::getValueBasic,
this
));
Problem is: on this line:
return std::shared_ptr<DelayedCaller>(new DelayedCaller(func));
I get "no matching function for call to 'DelayedCaller::DelayedCaller(std::_Bind(AppBaseLogic*, std::_Placeholder<1>)>&)'
return std::shared_ptr(new DelayedCaller(func));"
This only happens when using the placeholder::_1. if I replace that with a known value of the correct type, it works, with the exception that the function gets called without any useful data of course.
So, I guess I need a way to store the function with placeholders that I don't know the type of?
Forgive me if I am getting names of things wrong. I am very new to c++, I have only started learning it the past few days.
**Edit: **
Ok, so I am just updating why I need to store functions like this.
I have a map in my event dispatcher that looks like this:
std::map< const char*, std::vector<DelayedCaller> > _observers;
I want to be able to call the function inside the "Delayed Caller" something like this:
void Dispatcher::post( const EventBase& event ) const
{
// Side Note: I had to do this instead of map.find() and map.at() because
// passing a "const char*" was not evaluating as equal to event.type() even
// though event.type() is also a const char*. So instead I am checking it
// myself, which is fine because it gives me a little more control.
std::string type(event.type());
for( auto const &x : _observers ) {
std::string type2(x.first);
if ( type == type2 ) {
auto&& observers = x.second;
for( auto&& observer : observers ) {
// event may be any descendant of EventBase.
observer.slot->call(event);
}
break;
}
}
}
My listeners currently look like this:
void AppBaseLogic::getValue(const EventBase &e) {
const EventDemo& demoEvent = static_cast<const EventDemo&>( e );
std::cout << demoEvent.type();
}
I am trying to store each function so that the argument may look like this:
void AppBaseLogic::getValue(const EventAnyDescendant &e) {
std::cout << e.type();
}
Hopefully that helps. Thank you all for taking the time to help me with this.
Side note on lambdas: Someone suggested them, I have know idea what they are or how to use them, but I am going to do some reaserch on them so see if that would make more sense. I am worried about maintainability with them though from what I have seen.
It isn't quite clear what your DelayedCaller is doing. If you refactor the code and get rid of it, you will get just this:
auto c1 = []() {myFunc1(123, 45.6);}; // or use bind, the result is exactly the same
auto c2 = []() {myFunc2("A string");};
vector<function<void()>> v {c1, c2};
v[0]();
v[1](); // ok
Now if you try to introduce the placeholder modification in this version, it becomes clear why it didn't work in the first place:
auto cSome = [](???) {getValueBasic(???)};
What do you replace the ??? with?
getValueBasic accepts some specific type of argument, and it will leak out into the cSome signature. No matter how many template wrappers you wrap it in, it will leak out into the signature of every wrapper up to and including the outermost one. bind and std::placeholders are not a magic wand capable of making it unhappen.
In other words, if you don't know the type of your function, you cannot call it (kind of obvious, isn't it?)
One way to type-erase the signature and have all callables to conform to the same type is to typecheck and typecast them at run time (a.k.a. dynamic_cast). Another one is double dispatch. Both methods are different incarnations of the same general idea of visitor. Google "the visitor pattern" for more info.
May be this suits you. using c++11
#include <iostream>
#include <functional>
#include <vector>
namespace test
{
std::vector<std::function<void()>> listeners;
template<typename F, typename... Args>
void add_listener(F call, Args&& ...args )
{
std::cout << "callback_dispatcher>" << __PRETTY_FUNCTION__ << "enter <<< " << std::endl;
auto invoke_me = [=]()mutable{
call(std::move(args)...);
};
listeners.push_back(invoke_me);
}
void dispatch_all()
{
for(auto func: listeners)
{
func();
}
}
}
int main()
{
std::cout << "Main entered..." << std::endl;
test::add_listener(
[](int a)
{
std::cout << "void(int) lambda dispatched with a = " << a << std::endl;
},
5
);
test::add_listener(
[](int a, std::string str)
{
std::cout << "void(int, string) lambda dispatched with a = " << a << ", str = " << str << std::endl;
},
10, "Hello World!"
);
test::dispatch_all();
std::cout << "Main exited..." << std::endl;
}
Output:
Main entered...
callback_dispatcher>void test::add_listener(F, Args&& ...) [with F = main()::<lambda(int)>; Args = {int}]enter <<<
callback_dispatcher>void test::add_listener(F, Args&& ...) [with F = main()::<lambda(int, std::__cxx11::string)>; Args = {int, const char (&)[13]}]enter <<<
void(int) lambda dispatched with a = 5
void(int, string) lambda dispatched with a = 10, str = Hello World!
Main exited...
Refer SO_QUESTION for why mutable and std::move is used when expanding args in a lambda.
Take a look at std::bind and perhaps std::mem_fn
The c+=11 version is able to do all sorts of clever transformations on your argument list to generate a function-like object.
Lambdas provide even more flexibility, of course, and you can mix them, mostly.
I see 2 main problems in your modified (method and placeholder) version of DelayedCaller
(1) now call() receive a parameter (of type T) so func_() is called with one parameter; but func_() remain defined of type std::function<void()>, so can't receive the parameter [this point is the reason of your "no matching function" error]
(2) if you templatize call(), receiving a parameter of with type T, it's necessary to templatize also the type of func_ that become std::function<void(T)>; so you have to templatize the full class.
Taking in count (1) and (2), and maintaining std::unique_ptr, I've rewritten your DelayedCaller as dcM1 (M for "method" and 1 for "1 parameter")
template <typename T>
class dcM1
{
public:
template <typename TFunction, typename TClass>
static std::unique_ptr<dcM1> setup (TFunction && a_func,
TClass && a_class)
{
auto func = std::bind(std::forward<TFunction>(a_func),
std::forward<TClass>(a_class),
std::placeholders::_1);
return std::unique_ptr<dcM1>(new dcM1(func));
}
void call( T v ) const
{ func_(v); }
private:
using func_type = std::function<void(T)>;
dcM1(func_type && a_ft) : func_(std::forward<func_type>(a_ft))
{ }
func_type func_;
};
and can be used as follows
auto cm1f = dcM1<int>::setup(&foo::func, &f);
auto cm1b = dcM1<long>::setup(&bar::func, &b);
cm1f->call(0);
cm1b->call(1L);
The following is a full working example
#include <iostream>
#include <string>
#include <functional>
#include <memory>
void myFunc1 (int arg1, float arg2)
{ std::cout << arg1 << ", " << arg2 << '\n'; }
void myFunc2 (char const * arg1)
{ std::cout << arg1 << '\n'; }
class dcVoid
{
public:
template <typename TFunction, typename... TArgs>
static std::unique_ptr<dcVoid> setup (TFunction && a_func,
TArgs && ... a_args)
{
return std::unique_ptr<dcVoid>(new dcVoid(
std::bind(std::forward<TFunction>(a_func),
std::forward<TArgs>(a_args)...)));
}
void call() const
{ func_(); }
private:
using func_type = std::function<void()>;
dcVoid(func_type && a_ft) : func_(std::forward<func_type>(a_ft))
{ }
func_type func_;
};
template <typename T>
class dcM1
{
public:
template <typename TFunction, typename TClass>
static std::unique_ptr<dcM1> setup (TFunction && a_func,
TClass && a_class)
{
auto func = std::bind(std::forward<TFunction>(a_func),
std::forward<TClass>(a_class),
std::placeholders::_1);
return std::unique_ptr<dcM1>(new dcM1(func));
}
void call( T v ) const
{ func_(v); }
private:
using func_type = std::function<void(T)>;
dcM1(func_type && a_ft) : func_(std::forward<func_type>(a_ft))
{ }
func_type func_;
};
struct foo
{ void func (int i) { std::cout << "foo func: " << i << std::endl; } };
struct bar
{ void func (long l) { std::cout << "bar func: " << l << std::endl; } };
int main ()
{
auto cv1 = dcVoid::setup(&myFunc1, 123, 45.6);
auto cv2 = dcVoid::setup(&myFunc2, "A string");
foo f;
bar b;
auto cm1f = dcM1<int>::setup(&foo::func, &f);
auto cm1b = dcM1<long>::setup(&bar::func, &b);
cv1->call();
cv2->call();
cm1f->call(0);
cm1b->call(1L);
}
Ok, So I know this has been sitting for a while. I've been doing heavy research into different event patterns trying to find something closer to what I was after. After pouring through everything, and with the advice of those who have left comments here, I have decided to use a Signal/Slot pattern, possibly the most widely used event pattern for C++. The way have have approached it is to have all of my "logic classes" (whether for a gui or for computation) keep a reference to a third "signal event holder class", which I am calling an event broker for simplicity. This is just about as good as I can get it. Any event that you might want to have can be added to this class, and it can be accessed and called from any class with a reference to the event broker. I found a pretty nice signal class made by Simon Schneegans, but I am actively trying to find/learn how to make something better (threadsafe, maybe faster?). If anyone is interested/looking for help like I was, you can find my super basic test case here:
https://github.com/Moonlight63/QtTestProject
Thanks!

Is there a template debugger?

Templates can be programs in themselves.
Is there a template debugger so you can step thru the "execution" of the template?
This would basically have to be something that is done during compile/link/codegen - and is distinct from debugging the generated program.
Even in many "primitive" environments where you cannot use a debugger, you can usually do "printf debugging". Is even that possible with templates?
edit: Another way to think about this is something like the C preprocessor. It is often very useful to generate "preprocessed" source code - the output from the preprocessor that the compiler is actually compiling - this lets you see what effect your macros are having. A template equivalent would be great - have the compiler output the non-template source code which cooresponds to the templated input. The closest you can get I suppose is a C++ to C translator. (Doesn't the comeau compiler do this?)
You might want to look at this patch for clang that outputs template instantiations.
Another simple tool is the error messages your compiler produces for attempting to instantiate an undefined template.
template< typename > struct TD;
template< typename T >
void your_template_function( T & param )
{
// Both of these produce an error about "undefined type TD< T > with T = ..."
TD< T > test1;
TD< decltype( param ) > test2;
}
This is explained in Scott Meyers CPPCon talk, right after the ring-tailed lemur slide.
On the last years c++ conference there was a talk to that topic. Some of the informations you can find here:
http://gsd.web.elte.hu/contents/articles/gpce06.pdf
and
http://patakino.web.elte.hu/ECOOP_Templight_Poster.pdf
I have no idea how functional that stuff now is, but it was a very interesting startpoint.
I personal wrote me some helper classes which are able to print me the given types like printf debugging for standard code. If the compilation fails it often gives a good error message while calling the DebugPrinter and if the program compiles but the result is really stupid because the type expansion is not what I expect the DebugPrinter helps me a lot!
template< typename T>
int DebugPrintArgs( T arg )
{
std::cout << arg << ", ";
return 0;
}
template <typename Head, typename ... T>
class DebugPrinter: public DebugPrinter<T...>
{
public:
DebugPrinter()
{
std::cout << "--------------------------" << std::endl;
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::cout << "--------------------------" << std::endl;
}
template< typename ...Y>
DebugPrinter( Y ... rest )
{
std::cout << "Construction of: " << __PRETTY_FUNCTION__ << " Values: " ;
ExpandWithConstructor{DebugPrintArgs( rest)...};
std::cout << std::endl;
}
};
template <typename Head>
class DebugPrinter< Head >
{
public:
DebugPrinter()
{
std::cout << "--------------------------" << std::endl;
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::cout << "--------------------------" << std::endl;
}
};

How to print input c++ function parameter values automatically

I was wondering if there is a macro or standard way (for debugging purposes) to automatically print the value of the parameters of a function f, just like __FUNCTION__ prints/shows the function signature? For example,
void foo(int x, string y) {
cout << __FUNCTIION_ARGS__ << endl;
}
should show the values of x, and y.
If there is no such magic the standard way, is it possible to write a macro/template to do this?
--Update--
Per #jxh's comment, if print inside the function in question is impossible with macro/templates, is it possible to do it automatically on the caller-side, with something like:
call(foo,x,y);
which prints every parameter value, and behaves the same with foo(x,y) as if it is called directly in every other aspect? If a value is not printable (e.g. pointers, functions), the wrapper call can just print an opaque value such as <ptr> or <noprint>.
Thanks
P.S. I am using gcc, (and also clang in the future).
My take on it :
#include <iostream>
// Dummy parameter-pack expander
template <class T>
void expand(std::initializer_list<T>) {}
// Fun
template <class Fun, class... Args>
typename std::result_of<Fun&&(Args&&...)>::type
call(Fun&& f, Args&&... args) {
// Print all parameters
std::cout << "Params : ";
expand({(std::cout << args << ' ', 0)...});
std::cout << '\n';
// Forward the call
return std::forward<Fun>(f)(std::forward<Args>(args)...);
}
// Random test function
int myFunc(std::string const &s, double d, int i) {
std::cout << s << ' ' << d << ' ' << i << '\n';
return 57;
}
int main()
{
// Painless call
std::cout << call(myFunc, "hello", 3.14, 42) << '\n';
return 0;
}
Output :
Params : hello 3.14 42
hello 3.14 42
57
Variadic templates are fun !
There is no macro for printing the arguments, but you can print the function prototype using the __PRETTY_FUNCTION__ macro

How to pass a variable number of arguments of varying types to functions in a C++11 function map?

I am attempting to learn C++11 and have started writing a program that reads a textfile into a vector of strings, then passes the vector to a function that will ask the user to select the name of the function they wish to apply to the vector.
I have a function map like so in C++11:
std::map<std::string, void(*)(std::vector<std::string>& v)> funcs
{
{"f1", f2},
{"f2", f2},
};
And I call it with the following function:
void call_function(std::vector<std::string>& v)
{
std::string func;
std::cout << "Type the name of the function: ";
std::cin >> func;
std::cout << "Running function: " << func << "\n";
funcs[func](v);
}
And two example functions would be:
void f1(std::vector<std::string>& v)
{
std::cout << "lol1";
}
void f2(std::vector<std::string>& v)
{
std::cout << "lol2";
}
As of right now, I am successfully able to pass my vector of strings to the functions by calling them from the function map, however, I want to be able to pass a variable number of arguments of varying types. What I want to be able to do is to change my functions to accept integer and string arguments, but not all of my functions will accept the same amount of arguments or arguments of the same type.
For example, I may want to allow one function that is in the map to accept a string and an integer as arguments while another function may only accept a single integer or a single string as the arguments.How can I accomplish this? I've been thus far unable to discover a means of passing variable arguments through map to my functions.
Is this possible with std::map? I was also looking into variadic templates in C++11, but I'm not really understanding them that well.
Can anyone provide any insight?
That could be perfectly achieved using variadic templates. For example:
template<typename... ARGS>
struct event
{
typedef void(*)(ARGS...) handler_type;
void add_handler(handler_type handler)
{
handlers.push_back(handler);
}
void raise_event(ARGS args...)
{
for(handler_type handler : handlers)
handler(args...);
}
private:
std::vector<handler_type> handlers;
};
void on_foo(int a,int b) { std::cout << "on foo!!! (" << a << "," << b << ")" << std::end; }
int main()
{
event<int,int> foo;
foo.add_handler(on_foo);
foo.raise_event(0,0);
}
This class represents an event. An event is really a set of callbacks of the specified signature (A function of two int parameters, in the example).