Expecting various argument types in c++ - c++

I'm creating an equivalent to JavaScript's console.log in C++, but am unsure how to have my function expect different types of arguments.
In JavaScript:
function print(arg)
{
if(typeof arg=="number") { ... }
if(typeof arg=="string") { ... }
}
Of course, JavaScript doesn't care what you give a function, but C++ does, so how can I have it catch any ( or at least specify types for it to accept ), to be handled later in the function itself?
All I have so far:
void print(string input)
{
cout << input << "\n";
}

You can accomplish this with a function template.
template <typename T>
void print(const T& output)
{
std::cout << output << "\n";
}
This will create a print function for each type you pass to it.
Edit:
From the comments if you want this to work with arrays as well then you can add
template<typename T, std::size_t N>
void print(T (&output)[N])
{
for (std::size_t i = 0; i < N; i++)
{
std::cout << output[i] << " ";
}
std::cout << "\n";
}
You cann see all of this working together in this Live Example

This is a solved problem.
std::cerr << "My console output with a number! " << 42 << std::endl;
This goes to stderr, an output stream typically handled by your shell differently than stdout, so as to aid in debugging and fault-finding. It's the perfect analogue to JavaScript's console.log, and it already exists.

You can use function templates as described by NathanOliver.
You can also use function overloading: just define multiple functions with the same name but different argument types. The compiler will choose the right one. Function overloading might be better than a template function depending on what you are doing. In particular, if every type of parameter requires a different function body to handle it, function overloading probably makes more sense than a template.

Related

Storing and calling functions of different arguments in one function container

Here is a sample design code of what I want to achieve. Basically I wanna store handler functions for different handlerNames and these handler functions can be of variable arguments.
The handler functions should be called on events with the required arguments are passed with Script::Handle(...)
How can I achieve this? Maybe its possible with Variadic Templates?
class Script
{
public:
Script() { /* ... */ }
template<typename TFunction>
void AddHandler(const char *handlerName, TFunction &&function)
{
_handlerMap[handlerName] = std::move(function);
}
void Handle(const char *handlerName, ...)
{
_handlerMap[handlerName](...);
}
private:
typedef std::map<std::string, std::function<void()>> HandlerMapType;
HandlerMapType _handlerMap;
};
//Handler functions
handlerOne() { std::cerr << "One"; }
handlerTwo(std::string a1, int a2) { std::cerr << "Two"; }
handlerThree(bool a1) { std::cerr << "Three"; }
int main(int argc, char **argv)
{
Script script;
script.AddHandler("One", std::bind(&handlerOne));
script.AddHandler("Two", std::bind(&handlerTwo));
script.AddHandler("Three", std::bind(&handlerThree));
script.Handle("One");
script.Handle("Two, "string", 96);
script.Handle("Three", true);
script.Handle("Three", "what should happen here?"); //String passed instead of bool
}
Let me prefix by saying that this is not a trivial thing to do in C++. And I will go as far to say that you should consider whether this is really something you need in your use case. In your example, you are asking for genericism that you can't really use. You will in any case need to know the signature of the function you are calling to call it properly; in that case what purpose is served by putting them in a container?
Generally, you'd do something like this if you are writing a middle layer of code. In your example, this would be equivalent to writing code that enables another user to call Handle. A common concrete example of this is to write a factory where objects in the factory may be instantiated using different arguments. However, it can't really be "different" arguments, at least not without some crazy casting. The solution is to make all the functions take the same argument, but make the argument a dynamic type that can store whatever arguments you want:
using argument_type = std::unordered_map<std::string, boost::any>;
void print(const argument_type & arg) {
auto to_print = boost::any_cast<std::string>(arg["to_print"]);
std::cerr << to_print << std::endl;
}
void print_none(const argument_type & arg) {
std::cerr << "none" << std::endl;
}
using my_func_t = std::function<void(const argument_type &)>;
std::vector<my_func_t> v;
v.emplace_back(print);
v.emplace_back(print_none);
// create some argument_types, feed them to f.
The above is not code that has been tested, nor with a working main, but I think this should give you a sense of how you could accomplish what you want.
edit: I thought about it a bit more, and I decided to elaborate a bit more on the "crazy casting" way. I suppose it's not really more crazy, but I strongly prefer what I showed above. The alternative is to completely type erase the functions themselves, and pass the arguments using a variadic template.
void print(std::string to_print) {
std::cerr << to_print << std::endl;
}
void print_none() {
std::cerr << "none" << std::endl;
}
std::vector<boost::any> v;
v.emplace_back(std::function<void(std::string)>(print));
v.emplace_back(std::function<void(void)>(print_none));
template <typename ... Args>
void call(const std::vector & funcs, int index, Args... args) {
auto f = boost::any_cast<std::function<void(Args...)>>(funcs[index]);
f(std::forward<Args>(args)...);
}
// unsure if this will actually work
call(f, 0, std::string("hello"));
The code above is very fragile though, because the types you pass to call will be deduced against, and then the cast will try to cast to a std::function that matches that signature. That exact signature. I don't have a lot of confidence that this will work out; if it's a reference, vs value, vs rvalue, etc. Casting back to a different std::function than what you put in is undefined behavior.
In summary, I'd either try to avoid needing to do this entirely, or go with the first solution. It's much less fragile, and it's better to be upfront about the fact that you are erasing the signatures of these functions.

C++, template or pointer to member function

I have a series of member functions that are all very similar, and I think I might be able to make my code more maintainable with a template or some other approach, but I am not sure how to do it.
Here is an example of one of my functions:
void CalController::bgc_cmd(const std::string& s) {
try {
this->cohort_ptr->md->set_bgcmodule(temutil::onoffstr2bool(s));
LOG(note) << "CalController turned bgc module to "
<< s <<" via cohort pointer...";
} catch (const std::runtime_error& e) {
LOG(warn) << e.what();
}
}
My other functions are identical except for:
function name (i.e. bgc_cmd(..), env_cmd(..), dsl_cmd(..)
member function (of the md class) that is called within the try...catch block
Essentially I'd like to avoid having to duplicate the try..catch block and LOG(..) message in each of my CalController::XXX_cmd(...) functions.
Using boost::function and or boost::bind would be fine, I am just going in circles and can't figure out how to set this up.
You could just write a member function to do all that stuff. No bind or template necessary since everything is a function on md that takes the same argument type. I'm going to use MD as the type of md, and I'm assuming onoffstr2bool returns a bool:
void set_cmd(void (MD::*fn)(bool), const std::string& name, const std::string& s)
{
try {
(this->cohort_ptr->md->*fn)(temutil::onoffstr2bool(s));
LOG(note) << "CalController turned " << name << " to "
<< s <<" via cohort pointer...";
} catch (const std::runtime_error& e) {
LOG(warn) << e.what();
}
}
Which you would then call like:
void CalController::bgc_cmd(const std::string& s) {
set_cmd(&MD::set_bgcmodule, "bgc module", s);
}
I think you can get what you want with a simple, regular function. No need for a template:
void CalController::do_cmd(boost::function<void (String)> fun, const std::string& s) {
try {
fun(temutil::onoffstr2bool(s));
LOG(note) << "CalController turned bgc module to "
<< s <<" via cohort pointer...";
} catch (const std::runtime_error& e) {
LOG(warn) << e.what();
}
}
Then you can make your other methods something like:
void CalController::bgc_cmd(const std::string& s) {
// here TypeOfMd is whatever the type is for this->cohort_ptr->md.
// This binds the "this pointer" for set_bgcmodule to this->cohort_ptr->md
do_cmd(boost::bind(&TypeOfMd::set_bgcmodule, this->chort_prt->md), s);
}
A few things to note here:
With C++11 lambdas and the new function classes boost isn't necessary
I think the above works, but I'm not sure that saving a few lines of code is worth the extra complexity and loss of readability. It may also get hard to maintain as you want to make minor changes like slightly different log messages for each method.
It's been a while since I wrote any C++ and even longer since I did any boost stuff so while I think the above is the right general idea, I'd be surprised if it actually compiled.
If using C++11, You can create a function with a more generic name, let's say exex_cmd.
You can then pass a lambda function as argument and execute it inside the try/catch block - no need for a template use.
//WARNING: Untested code - the point is that you get the idea. Modify at will.
void CalController::exec_cmd(const std::function<void (void)> func) {
try {
//Invoke lambda.
//The string is passed via closure implementation,
//but you can always pass it as normal argument if you want.
func();
LOG(note) << "CalController turned bgc module to "
<< s <<" via cohort pointer...";
} catch (const std::runtime_error& e) {
LOG(warn) << e.what();
}
}
Then, create 3 wrapper methods, invoking exec_cmd, but passing a different lambda as argument:
void CalcController::bgc_cmd(const std::string& s){
CalcController::exec_cmd([=] () {
//Taking closures into control, to avoid passing the string as argument.
this->cohort_ptr->md->set_bgcmodule(temutil::onoffstr2bool(s));
})
}
void CalcController::env_cmd(const std::string& s){
CalcController::exec_cmd([=] () {
//different function invocation here.
})
}
Similarly, you can do it for all your functions.
You can look here for more about C++11's lambdas.
A similar approach in plain-old C++ is to define a function pointer type and pass a function pointer to your exec_cmd, create normal functions following the type signature and pass them as arguments, or pass a member function pointer - You can look at Barry's answer for that.

Passing anonymous function as only parameter to another function (C++)

I've read posts/articles about lambdas, function pointers, anonymous functions in general and other related things but nothing I've seen (I think) has hit on exactly what I'm looking to do.
It seems like accomplishing this should be pretty simple, but say I have a function containing things I always want to do when called, but each time I call it I want it to run a function I describe (and only need to use once) in the argument (this anonymous function being the only argument).
Assuming this function which accepts my anonymous function as its argument is in main.cpp so it's called from main is it possible to implement this in a simple way?
Basically I'm trying to figure out the syntax in C++ for going from this:
// Some function with partially duplicated code
void OriginalA()
{
DoThingsA();
// unique code
DoThingsB();
}
// Another function with partially duplicated code
void OriginalB()
{
DoThingsA();
// unique code
DoThingsB();
}
To this:
// Encapsulate shared functionality
// <param name="action">User defined action</param>
void UniqueWrapper(Action action)
{
DoThingsA();
action();
DoThingsB();
}
// New implmentation of A
void NewA()
{
UniqueWrapper(() =>
{
// unique code
});
}
// New implementation of B
void NewB()
{
UniqueWrapper(() =>
{
// unique code
});
}
Which I found as #1 here: http://www.wildbunny.co.uk/blog/2012/11/01/10-steps-to-becoming-a-better-programmer/
But a setup like this where literally all you would have to do for the call is:
theFunctionName(() => { /*unique things to do*/ });
If this ^^ is legal calling syntax then I'm just not sure how the parameter looks in the definition of theFunctionName, clearly it isn't (Action action) like in the example above.
Replace the Action argument with:
template<typename Function>
void UniqueWrapper(Function action) {
DoThingsA();
action(); // call the passed in function
DoThingsB();
};
Call it like this:
void NewA() {
UniqueWrapper([]() {});
// ^^^^^^^
// C++11 lambda syntax
}
Instead of a lambda you can also use function pointers, member functions (using std::mem_fn), or functors. Every kind of callable object will work.
There are multiple ways to do this, but not all will work on all platforms (e.g. because they'd require C++11 features (lambdas).
The more classic approach would be something like this (without an anonymous function):
#include <iostream>
typedef void(*Action)();
void UniqueWrapper(Action action) {
std::cout << "Generic Code 1" << std::endl;
action();
std::cout << "Generic Code 2" << std::endl;
}
void CustomAction(void) {
std::cout << "Custom Code" << std::endl;
}
int main(int argc, char **argv) {
UniqueWrapper(&CustomAction);
return 0;
}
Of course you could use some macro shenanigans to make this more "dynamic".
Once you accept C++11 code as well (which is required to have lambdas as explained), you can do something like this:
#include <iostream>
typedef void(*Action)();
void UniqueWrapper(Action action) {
std::cout << "Generic Code 1" << std::endl;
action();
std::cout << "Generic Code 2" << std::endl;
}
int main(int argc, char **argv) {
UniqueWrapper([](){
std::cout << "Custom Code" << std::endl;
});
return 0;
}
Of course, there's room for more changes, for example you could use std::function rather than a function pointer.

Indefinite amount of generic types in template?

I want to make a custom print function that takes any amount of arguments and prints them all on new lines.
In javascript, the document.write and console.log functions can do this because javascript stores all arguments in an array. To my knowledge, c++ doesn't do this and can't because of type restrictions.
So is there a proper way to do this in c++? Take any amount of arguments, regardless of type, and print them all?
Yes there is with the new C+11 standard. Please take a look at this article :
http://en.wikipedia.org/wiki/Variadic_template
There is a pretty nice example also you can use as a starter.
You can use a variadic function, similar to printf, but you will still need to know the types of the arguments and how many there are to be able to access them properly.
A better approach would probably be to do something similar to how the << operator was overloaded for ostream or use a chainable function. You will in the end still be limited to types (or supertypes with virtual functions) you know about.
From Bjarne himself:
http://www2.research.att.com/~bs/C++0xFAQ.html#variadic-templates
His code as of today:
void printf(const char* s)
{
while (s && *s) {
if (*s=='%' && *++s!='%') // make sure that there wasn't meant to be more arguments
// %% represents plain % in a format string
throw runtime_error("invalid format: missing arguments");
std::cout << *s++;
}
}
template<typename T, typename... Args> // note the "..."
void printf(const char* s, T value, Args... args) // note the "..."
{
while (s && *s) {
if (*s=='%' && *++s!='%') { // a format specifier (ignore which one it is)
std::cout << value; // use first non-format argument
return printf(++s, args...); // "peel off" first argument
}
std::cout << *s++;
}
throw std::runtime error("extra arguments provided to printf");
}

template functions, how to send different structures and create a if/else statement based on type?

i'm trying to build a general purpose template function which should function with 2 different type of structure i'll write an example
struct sa {
int a;
int b;
char d;
}
struct sb {
int a;
int b;
int c;
}
template < class T>
void f_print(T & s_passed, bool s_typeB){
std::cout << s_passed.a << endl ;
std::cout << s_passed.b << endl ;
if(s_typeB == false){
std::cout << s_passed.d << endl ;
}else{
std::cout << s_passed.c << endl ;
}
}
then in main:
{
struct sa str_TEST_A ;
struct sb str_TEST_B ;
f_print(str_TEST_A,false);
f_print(str_TEST_B,true);
}
now , this is a short example of my issue where i'm handling much more complicated structures, anyway what i get is
error: 'struct sa' has no member named 'd'
the problem is that the gnu c++ compiler didn't recognize that not all operations in the function are execute when struct sa is passed, and d is printed only when sb is passed,
how i can fix this without creating a duplicated function 1 for each structure type?
thank you :)
Francesco
You could move the specialized parts in separate functions and call these from your generic template:
void f_print_special(sa & s_passed) {
std::cout << s_passed.d << endl ;
}
void f_print_special(sb & s_passed) {
std::cout << s_passed.c << endl ;
}
template <class T>
void f_print(T & s_passed) {
std::cout << s_passed.a << endl ;
std::cout << s_passed.b << endl ;
f_print_special(s_passed);
}
sth has the correct answer. However, if you need a more generic solution, in that say the function that accepts sb type could accept any type that implements the concept "has C" (or whatever) then you need to use tag based dispatch. I'd suggest looking it up because though I might be able to describe one hypothetical situation that may or may not resemble your real problem, I couldn't get them all.
It's not just g++. That's invalid C++. Every statement in a function (template or not) must be valid, even if you can "prove" it's not executed.
What's so bad about giving them separate functions? Of course, you can deal with some common subparts by calling another subfunction.
If you want the functions to have the same name, go ahead and do that. Function overloading will handle it.
Perhaps this is just a test case for you in writing templates but a more natural implementation would be to have sa and sb inherit from a common base struct sbase say, with members a and b only, and then have sa and sb implement their own operator<<, delegating to the base operator<< for the common parts.