I have a problem in C++ that is similar to this example problem. In this case I have two member-functions that have an identical interface. Based on the information in a string passed to the super function, I would like to assign one of the two member functions to the variable class_func. Is there a way to do this?
// test.hpp
class TestClass
{
public:
double master_function(double a, double b, std::string func_name);
private:
double add(double a, double b);
double subtract(double a, double b);
};
// test.cpp
double TestClass::master_function(double a, double b, std::string func_name)
{
if (func_name == std::string("Add") const auto& class_func = add;
else const auto& class_func = subtract;
return class_func(a, b);
}
// =========================================================================
double TestClass::add(double a, double b)
{
return a + b;
}
// =========================================================================
double TestClass::subtract(double a, double b)
{
return a - b;
}
In other words, I am trying to assign the member-function add or subtract to the name class_func, so the code underneath the if statement in master_function can be uniform regardless of which function the user wants to use. In the form shown below I get the error Reference to non-static member function must be called out, but I am not totally sure what this means or how to fix it. In addition, I am using a C++17 compiler, so if there is a modern approach that works best with C++17 I would be interested in learning it.
The term you are looking for is member function pointer, but we can do without explicitly specifying that type. The problem with your code is not only in the way you try to refer to a member function (that would be &TestClass::add), but also that you create those aliases in a nested scope (under if/else), meaning they won't be visible in the return statement.
The simplest change is this:
auto class_func = &TestClass::add; // pick one default
if (func_name == "Subtract")
{
class_func = &TestClass::subtract;
}
else
{
assert(func_name == "Add"); // optional
}
return class_func(a, b);
This works because the add and subtract functions have the exact same type:
double (TestClass::*)(double a, double b)
But yeah, why are those functions not static? They do not work with a class' instance. Make them static and the above will still work, just note that the type of class_fun will be a simple function pointer:
double (*)(double a, double b)
Now that you know the types, you could change this in a way that does not privilege one function before the other in the code:
decltype(&TestClass::add) class_func = nullptr;
if (func_name == "Add")
{
class_func = &TestClass::add;
}
else if (func_name == "Subtract")
{
class_func = &TestClass::subtract;
}
assert(class_func != nullptr);
return class_func(a, b);
As mentioned in the comments, as that if-else chain starts to get longer, it makes more and more sense to use a (hash)map between strings and function pointers.
Related
I have two functions with the same name but different return types. I want to run the function based on their third parameter. If the third parameter is true I want to run the first and If the parameter is false to run the second function. I was trying different things on my own because I couldn't find information online and I wasn't sure how is this called. Here is what I tried to do:
static int function(int a, int b, const bool=true);
static std::string function(int a, int b, const bool=false);
I would be grateful if someone can explain how to do this or at least give me a link to some information.
This solution is not about having two different functions but if you wanted the function to return a different type depending on the bool value using boost::any.
boost::any function(int a, int b, const bool c) {
std::string str = "Hello world!";
int num = 10;
if ( c ) {
return boost::any(num);
} else {
return boost::any(str);
}
}
This would use the third parameter in the function in order to decide which return you should do. Depending on how big function is this might be a worse solution but if you really wanted to use a boolean as a parameter I believe this should work.
Docs: Boost
Related question to this answer: Function which returns an unknown type
You can create a function template and add specializations for the different return types. Then you could use the bool argument as a template parameter:
template<bool>
auto function(int, int);
template<>
auto function<true>(int a, int b)
{
// ...
return int{};
}
template<>
auto function<false>(int a, int b)
{
// ...
return std::string{};
}
The functions would then be called like this:
int a = function<true>(1,2);
std::string b = function<false>(1,2);
Here's a demo.
Note the important caveat that the bool parameter must be known at compile time, and can't be a run time argument.
While this technique will work, do be aware that this will confuse a lot of c++ programmers. They usually expect a function to always return a particular type.
More relevant to your question; this is not actually going to make the code much more readable. Instead, having separate named functions is probably a more readable approach:
int int_function(int a, int b);
std::string str_function(int a, int b);
which could be called like this:
int a = int_function(1,2);
std::string b = str_function(1,2);
I have two functions which use the same doubles ie like
in the .h I declare
class MyClass : {
public :
double arg1, arg2;
void getVarA(double a, double b);
void getVarB(double a, double b);
void Reset();
}
and in my .C I have something like
void MyClass::Reset(){
arg1 = 0.0f;
arg2 = 0.0f;
}
void MyClass::getVarA(double a, double b){
arg1+=2*a;
arg2+=2*b;
return arg1-arg2;
}
void MyClass::getVarB(double a, double b){
arg1+=2+a;
arg2+=2+b;
return arg1-arg2;
}
The problem is that in principle I want to create a copy of arg1,arg2 each one taking values in each function (ie in each function to be possible to take different values) so that arg1,arg2 dont "speak" between the two different functions and whenever I change the arg1 in getVarA function not to commute with the arg1 in getVarB function.
Sorry, probably my example is poorly phrased but I am just newbie..
thanks
Make your variables arg1, arg2 as function local variables.
void MyClass:getVarA(double a, double b) {
double arg1, arg2;
arg1+=2*a;
arg2+=2*b
return arg1-arg2
}
void MyClass:getVarB(double a, double b) {
double arg1, arg2;
arg1+=2+a;
arg2+=2+b
return arg1-arg2
}
They will become different variables. None of changes made in getVarA arg1, arg2 will affect arg1, arg2 from getVarB
EDIT
According to #harper comment, it is strongly recommended to avoid uninitialized variables. You can't assume initial value of arg1 and arg2 variables. Your should explicit set initial value
double arg1 = 0.0;
double arg2 = 0.0;
"The problem is that in principle I want to create a copy of arg1,arg2"
You can do exactly that:
void MyClass::getVarA(double a, double b)
{
double arg1Copy = arg1;
double arg2Copy = arg2;
arg1Copy+=2*a;
arg2Copy+=2*b;
return arg1Copy-arg2Copy;
}
Now arg1 and arg2 are not modified by your method. In fact you can even declare your method as const to inform the compiler that you do not want the data members to actually be modified by your method.
This answer is based on the following interpretation of your question:
Each of the getVar functions is supposed to remember something about previous calls. The value returned from a function call is supposed to change based on what calls were made to that function in the past. For example, if you ran this code, x1 and x2 would have different values:
MyClass mc;
double x1 = mc.getVarA(1,1);
double x2 = mc.getVarA(1,1);
If you want x1 and x2 to have different values (because the first call is supposed to change what values are used in the second call), then this answer is appropriate. If you want x1 and x2 to have the same value (because you don't want getVarA to remember anything about previous function calls), nnesterov's suggestion to use local variables is a better answer than this one.
You want what is remembered about calls to getVarA to be independent from what is remembered about calls to getVarB.
With that in mind, here's the .h:
class MyClass {
public :
double _varA1, _varA2;
double _varB1, _varB2;
MyClass();
double getVarA(double a, double b);
double getVarB(double a, double b);
void Reset();
};
and here's the .c:
MyClass::MyClass(){
Reset();
}
void MyClass::Reset(){
_varA1 = 0.0;
_varA2 = 0.0;
_varB1 = 0.0;
_varB2 = 0.0;
}
double MyClass::getVarA(double a, double b){
_varA1 += 2*a;
_varA2 += 2*b;
return _varA1 - _varA2;
}
double MyClass::getVarB(double a, double b){
_varB1 += 2+a;
_varB2 += 2+b;
return _varB1 - _varB2;
}
Things to notice:
Each of the two get functions has its own set of instance variables. That way you can change one function's data without changing the other function's data.
The constructor calls Reset() so that the variables are initialized when you first create an instance of the class. That way you can predict what will happen the first time you call each get function.
The return type of the get functions has been changed to double, to match the implementation.
Say I have a C++ function that looks like this:
double myfunction(double a, double b) {
// do something
}
Which I then call like this:
double a = 1.0;
double b = 2.0;
double good_r = myfunction(a, b);
double bad_r = myfunction(b, a); // compiles fine
I would like to make sure that a and b are never provided in the wrong order.
What is the best way to ensure this in C++?
Other languages allow named parameters, like this:
double good_r = myfunction(a=a, b=b);
double bad_r = myfunction(a=b, b=a); // mistake immediately obvious
double bad_r = myfunction(b=b, a=a); // compiles fine
Or perhaps the problem can be partly solved using types, i.e.
double my_type_safe_function(a_type a, b_type b) {
// do something
}
a_type a = 1.0;
b_type b = 2.0;
double good_r = myfunction(a, b);
double bad_r = myfunction(b, a); // compilation error
EDIT: A couple of people have asked what I mean by the "wrong order." What I mean is that, in real code a and b have some significance. For example, the arguments might instead be height and width. The difference between them is very important for the function to return the correct result. However, they are both floats and they both have the same dimensions (i.e. a length). Also, there is no "obvious" order for them. The person writing the function declaration may assume (width, height) and the person using the function may assume (height, width). I would like a way to ensure this doesn't happen by mistake. With two parameters it is easy to be careful with the order, but in a large project and with up to 6 arguments mistakes creep in.
Ideally I would like the checks to be done at compile time, and for there to be no performance hit (i.e. at the end of the day they are treated as plain old floats or whatever).
How about this:
struct typeAB {float a; float b; };
double myfunction(typeAB p) {
// do something
return p.a - p.b;
}
int main()
{
typeAB param;
param.a = 1.0;
param.b = 2.0;
float result = myfunction(param);
return 0;
}
Of course, you can still mess up when you assign your parameter(s) but that risk is hard to avoid :)
A variant is to have one struct per "new" type, and then make them go away in optimized builds using macros.
Something along these lines (only slightly tested, so it could be way off):
#define SAFE 0
#if SAFE
#define NEWTYPE(name, type) \
struct name { \
type x; \
explicit name(type x_) : x(x_) {}\
operator type() const { return x; }\
}
#else
#define NEWTYPE(name, type) typedef type name
#endif
NEWTYPE(Width, double);
NEWTYPE(Height, double);
double area(Width w, Height h)
{
return w * h;
}
int main()
{
cout << area(Width(10), Height(20)) << endl;
// This line says 'Could not convert from Height to Width' in g++ if SAFE is on.
cout << area(Height(10), Width(20)) << endl;
}
I think you already provided the easiest solution, using types.
One alternative could be using a builder class and method chaining.
Like:
class MyfunctionBuilder {
MyFunctionBuilder & paramA(double value);
MyFunctionBuilder & paramB(double value);
double execute();
(...)
}
Which you would use like this:
double good_r = MyFunctionBuilder().paramA(a).paramB(b).execute();
But this is a lot of extra code to write!
What is the "wrong order" actually? In this example of yours
double myfunction(double a, double b) {
// do something
}
double a = 1.0;
double b = 2.0;
double good_r = myfunction(a, b);
double bad_r = myfunction(b, a);
how do you actually want to know if this is the right order? What if the variables would be named "quapr" and "moo" instead of "a" and "b"? Then it would be impossible to guess whether the order is right or wrong just by looking at them.
With this in mind, you can do at least two things. First, is to give meaningfull names to the arguments, e.g.
float getTax( float price, float taxPercentage )
instead of
float getTax( float a, float b )
Second, do the necessary checks inside:
float divide( float dividend, float divisor )
{
if( divisor == 0 )
{
throw "omg!";
}
}
It is possible to do more complex checks, such as making a functor, and setting it's parameters explicitly, but in most of the cases that just complicates things without much benefit.
I need to find some way to mock an overload of a function return type in C++.
I know that there isn't a way to do that directly, but I'm hoping there's some out-of-the-box way around it.
We're creating an API for users to work under, and they'll be passing in a data string that retrieves a value based on the string information. Those values are different types. In essence, we would like to let them do:
int = RetrieveValue(dataString1);
double = RetrieveValue(dataString2);
// Obviously, since they don't know the type, they wouldn't use int =.... It would be:
AnotherFunction(RetrieveValue(dataString1)); // param of type int
AnotherFunction(RetrieveValue(dataString2)); // param of type double
But that doesn't work in C++ (obviously).
Right now, we're having it set up so that they call:
int = RetrieveValueInt(dataString1);
double = RetrieveValueDouble(dataString2);
However, we don't want them to need to know what the type of their data string is.
Unfortunately, we're not allowed to use external libraries, so no using Boost.
Are there any ways we can get around this?
Just to clarify, I understand that C++ can't natively do it. But there must be some way to get around it. For example, I thought about doing RetrieveValue(dataString1, GetType(dataString1)). That doesn't really fix anything, because GetType also can only have one return type. But I need something like that.
I understand that this question has been asked before, but in a different sense. I can't use any of the obvious answers. I need something completely out-of-the-box for it to be useful to me, which was not the case with any of the answers in the other question asked.
You've to start with this:
template<typename T>
T RetrieveValue(std::string key)
{
//get value and convert into T and return it
}
To support this function, you've to work a bit more, in order to convert the value into the type T. One easy way to convert value could be this:
template<typename T>
T RetrieveValue(std::string key)
{
//get value
std::string value = get_value(key, etc);
std::stringstream ss(value);
T convertedValue;
if ( ss >> convertedValue ) return convertedValue;
else throw std::runtime_error("conversion failed");
}
Note that you still have to call this function as:
int x = RetrieveValue<int>(key);
You could avoid mentioning int twice, if you could do this instead:
Value RetrieveValue(std::string key)
{
//get value
std::string value = get_value(key, etc);
return { value };
}
where Value is implemented as:
struct Value
{
std::string _value;
template<typename T>
operator T() const //implicitly convert into T
{
std::stringstream ss(_value);
T convertedValue;
if ( ss >> convertedValue ) return convertedValue;
else throw std::runtime_error("conversion failed");
}
}
Then you could write this:
int x = RetrieveValue(key1);
double y = RetrieveValue(key2);
which is which you want, right?
The only sane way to do this is to move the return value to the parameters.
void retrieve_value(std::string s, double& p);
void retrieve_value(std::string s, int& p);
<...>
double x;
retrieve_value(data_string1, x);
int y;
retrieve_value(data_string2, y);
Whether it is an overload or a specialization, you'll need the information to be in the function signature. You could pass the variable in as an unused 2nd argument:
int RetrieveValue(const std::string& s, const int&) {
return atoi(s.c_str());
}
double RetrieveValue(const std::string& s, const double&) {
return atof(s.c_str());
}
int i = RetrieveValue(dataString1, i);
double d = RetrieveValue(dataString2, d);
If you know your value can never be something like zero or negative, just return a struct holding int and double and zero out the one you don't need...
It's a cheap and dirty, but easy way...
struct MyStruct{
int myInt;
double myDouble;
};
MyStruct MyFunction(){
}
If the datastrings are compile-time constants (as said in answering my comment), you could use some template magic to do the job. An even simpler option is to not use strings at all but some data types which allow you then to overload on argument.
struct retrieve_int {} as_int;
struct retrieve_double {} as_double;
int RetrieveValue(retrieve_int) { return 3; }
double RetrieveValue(retrieve_double) { return 7.0; }
auto x = RetrieveValue(as_int); // x is int
auto y = RetrieveValue(as_double); // y is double
Unfortunately there is no way to overload the function return type see this answer
Overloading by return type
int a=itoa(retrieveValue(dataString));
double a=ftoa(retrieveValue(dataString));
both return a string.
As an alternative to the template solution, you can have the function return a reference or a pointer to a class, then create subclasses of that class to contain the different data types that you'd like to return. RetrieveValue would then return a reference to the appropriate subclass.
That would then let the user pass the returned object to other functions without knowing which subclass it belonged to.
The problem in this case would then become one of memory management -- choosing which function allocates the returned object and which function deletes it, and when, in such a way that we avoid memory leaks.
The answer is simple just declare the function returning void* type and in the definition return a reference to the variable of different types. For instance in the header (.h) declare
void* RetrieveValue(string dataString1);
And in the definition (.cpp) just write
void* RetrieveValue(string dataString1)
{
if(dataString1.size()<9)
{
static double value1=(double)dataString1.size();
return &value1;
}
else
{
static string value2=dataString1+"some string";
return &value2;
}
}
Then in the code calling RetrieveValue just cast to the right value
string str;
string str_value;
double dbl_value;
if(is_string)
{
str_value=*static_cast<*string>(RetrieveValue(str));
}
else
{
dbl_value=*static_cast<*double>(RetrieveValue(str));
}
Since you used an example that wasn't really what you wanted, you threw everyone off a bit.
The setup you really have (calling a function with the return value of this function whose return type is unknowable) will not work because function calls are resolved at compile time.
You are then restricted to a runtime solution. I recommend the visitor pattern, and you'll have to change your design substantially to allow for this change. There isn't really another way to do it that I can see.
I am assuming that the function already has a return value so that cannot be added.
What I came up with to solve this problem is to add extra pointer parameters which default to nullptr.
Before:
bool fun(double a, std::vector<std::randomexample> const & b)
After:
bool fun(double a, std::vector<std::randomexample> const & b, int* extraoutput = nullptr)
and use it like this
if(extraoutput)
*extraoutput = whatever;
But that's just what I came up with.
I would like to know if there is a better way to do this. Note that "whatever" is already in the function.
If for some reason you need binary as well as (mostly) source compatibility[*]:
Before:
bool fun(double a, std::vector<std::randomexample> const & b) {
// do stuff
return true;
}
After:
bool fun(double a, std::vector<std::randomexample> const & b, int* extraoutput) {
// do stuff
if(extraoutput)
*extraoutput = whatever;
return true;
}
bool fun(double a, std::vector<std::randomexample> const & b) {
return fun(a, b, nullptr);
}
If you don't want function overloading (for example if fun is part of an extern "C" interface), then you don't actually have to call the new function fun. It could just as well be fun2.
[*] As AndreyT points out, the source compatibility of your solution is limited. Calls to your old function will call your new function fine, but some other things that you might do with the old function will not work fine (since you have changed its type).
There's actually a source incompatibility in my code too. void(*foo)() = (void(*)()) fun; is allowed before the overload is added, but afterwards it's ambiguous. If you want to support code that does that, then that's a second reason not to want function overloading.
Normally, I add a method with the extra parameter, and call that one with a default value from the former method:
//foo v1
void foo( S s ) {
... stuff with s;
};
//codeA_v1:
S s;
foo(s);
//codeB_v1
S s2;
foo(s2);
Then, I add a method with an extra parameter:
void foo(S s){ foo(s, default_value_for_T); }
void foo(S s, T t){
... stuff with s and t
}
//codeA_v1 == codeA_v2
S s;
foo(s);
//codeB_v2
S s;
T t;
foo(s,t);
This is an extended comment. As alredy suggested by the others, you'd better overload the function in order to provide both source and binary compatibility. The reason to do so is that by introducing a change in the function signature, you also change the mangled symbol name, e.g. from _Z3fundRKSt6vectorISt13randomexampleSaIS0_EE to _Z3fundRKSt6vectorISt13randomexampleSaIS0_EEPi. This would break binary compatibility with all other objects that call fun() by its old mangled name. If fun() is part of a dynamically linked library, it will break all existing binaries that link against it since the dynamic linker would no longer be able to resolve the _Z3fundRKSt6vectorISt13randomexampleSaIS0_EE symbol reference. If you go with the overloaded function version, the old mangled symbol would still exist and binary compatibility would be retained.
As stated by others, this will be your final product.
bool fun(double a, std::vector<std::randomexample> const & b){
return fun(a,b,0);
}
bool fun(double a, std::vector<std::randomexample> const & b, int* extraoutput = 0){
// have fun!
if(extraoutput) *extraoutput = whatever;
return true;
}
You can try to implement genernic Observer pattern.
Here is a like:
http://sourcemaking.com/design_patterns/observer
It will be better for the future when you will want to add more parameters. If you cant derive then passing as a parameter will be solution too.
As i understand you have to do it in this function, otherwise yes overload is a good solution.
It doesnt break a binary compability otherwise to other solution.