Hi I am trying to get to grips with functors. Here is a simple example
struct A {
double b,c;
A(const double bb, const double cc) : b(bb), c(cc) {}
double operator()(const double x, const double y) {
return b*c*x*y;
}
};
I would like to know if it is possible to overload A such that it could be passed b, c and also e.g. x reusing the code in the operator(). My overall interest is to not have to re-write lengthy code in operators multiple times and to better understand the best practices for doing this.
Thanks!
I would like to know if it is possible to overload A such that it could be passed b, c and also e.g. x reusing the code in the operator().
Yes, it is not difficult to do that.
double operator()(double x, double y) // Remove the const. It's useless.
{
// Call the other overload using the member data.
return (*this)(b, c, x, y);
}
double operator()(double bb, double cc, double x, double y)
{
// Not using any member data at all.
return bb*cc*x*y;
}
One method of doing this is with std::bind in <functional>. This returns a closure that you can call without arguments. An alternative would be to create a new constructor with default arguments for a and b, or a derived class, and overload it to have:
double operator()(const double x = m_x, const double y = m_y);
As a side note, please don't use the same names for members and arguments of member functions; that creates ambiguity about which you mean and could even cause bugs if you rename a parameter later.
Related
If I'm given a struct variable like:
struct Quaternion {
float x;
float y;
float z;
float w;
}
But I need to call a function expecting a
struct Vector {
float x;
float y;
float z;
float w;
}
Is there a way in C++ to cast a variable of type Quaternion to type Vector?
You can write a converting constructor:
struct Quaternion {
float x;
float y;
float z;
float w;
explicit Quaternion(const Vector& vec) : x(vec.x),y(vec.y),z(vec.z),w(vec.w) {}
}
And similar for the other way.
In case you are looking for a way that does not require to copy the members, then I am not aware of a portable way to do that, and members having the same name does not help for that.
On the other hand, having same named members helps to write generic code like this:
template <typename T>
void foo(const T& t) {
std::cout << t.x << t.y << t.z << t.w;
}
You can call this with either a Quaternion or a Vector without needing to convert between them.
In case you cannot modify any existing code (not the structs nor the function you want to call), you can write a simple function to do the conversion (as suggested by ShadowRanger in a comment):
Vector Quat2Vect(const Quaternion& q) {
return {q.x,q.y,q.z,q.w};
}
If, as you said in a comment, you can't change to the two types, you could possibly "solve" the problem by using yet another type:
struct MyVector {
float x;
float y;
float z;
float w;
operator Quaternion() { return Quaternion{x, y, z, w}; }
operator Vector() { return Vector{x, y, z, w}; }
};
My advice: It's probably better to pick one or the other as the main type in your code and use a separate conversion function.
What I think you're hoping for, given that you specifically asked about "cast", is to use a cast to go from one to the other.
Vector v = {1, 2, 3, 4};
Quaternion* q = reinterpret_cast<Quaternion*>(&v);
do_something_with_quart(*q); // Could modify v if pass by reference
Strictly speaking, this is undefined behaviour, although it is overwhelmingly likely to work in practice, but I still wouldn't recommend it. If you're really desparate to do something cast like, it's legal to use memcpy so long as the member variables are the same type in the same order (and there are no virtual methods):
Vector v = {1, 2, 3, 4};
Quaternion q;
memcpy(&q, &v, sizeof(v));
do_something_with_quart(q);
memcpy(&v, &q, sizeof(v)); // Copy back any change
Although the language and documentation describes memcpy as a copying function, it has certain magical properties that often in practice make it identical to the previous block of code. But I would also strongly advise against this. I mean, yuck! Just look at it!!
This is just an addition to largest_prime_is_463035818's answer to point out that the members don't have to have the same name in order to write a generic function to use them. So long as there are an equal number of members, all are publicly accessible, and they have the same types, you can decompose objects with a structured-binding and use that.
template <typename T>
void foo(const T& t) {
auto const & [x, y, z, w] = t;
std::cout << x << y << z << w;
}
I have a class which has a few large fields (say, some big matrices) and has member functions to compute these matrices (the actual number of the matrices is bigger, of course)
class MyClass {
protected:
MatrixType m_11, m_12;
public:
void compute_m_11(double x);
void compute_m_12(double x);
}
Now, the computation code is very similar, and the most complex part is correct indexing of the matrix elements (which is the same for all the matrices involved). So I was thinking about splitting the indexing and the computation into separate functions: a compute_matrix function which will perform the indexing and call a compute_element function for each set of indexes in the matrix. This would greatly improve code readability and ease debugging.
So the compute_matrix function would take a MatrixType reference to the class field which I need to fill in and a std::function which would perform the actual computation. I obviously want to avoid writing anything that will involve additional copying of the matrices, since they can be quite large.
So, the questions are:
Is it legal/efficient to pass a reference to a class field to a class member function?
If so, do I need to use std::bind to pass the computation member functions? The compute_elements functions need to access some other fields of MyClass.
This is what I have in mind:
class MyClass {
protected:
MatrixType m_11, m_12;
double compute_elements_m11(int i, int j, double x);
double compute_elements_m12(int i, int j, double x);
void compute_matrix(MatrixType &m, double x, std::function<double(int, int, double) > f);
public:
void compute_m_11(double x) {compute_matrix(m_11, x, compute_elements_m11);};
void compute_m_12(double x) {compute_matrix(m_12, x, compute_elements_m12);};
}
It is legal (and not that uncommon) to pass a member reference, but your function type is wrong.
You could use std::bind, or you could use a plain pointer-to-member:
class MyClass {
protected:
MatrixType m_11, m_12;
double compute_elements_m11(int i, int j, double x);
double compute_elements_m12(int i, int j, double x);
void compute_matrix(MatrixType &m, double x, double (MyClass::*f) (int, int, double);
public:
void compute_m_11(double x) {compute_matrix(m_11, x, &MyClass::compute_elements_m11);};
void compute_m_12(double x) {compute_matrix(m_12, x, &MyClass::compute_elements_m12);};
};
std::bind and std::function gives a more flexible implementation though.
Sure it's not uncommon to pass a class attribute to an internal member function and you can also use std:bind to call the member function, but the question is do you really need that or can you just use a simple "if" or something similar to decide what to use? I'd say it depends on how many choices your code path has to decide that better.
Why would you pass a reference to a class field to a class member function? A better solution would be to implement a get method and use that in the compute_matrix function. Your class will then look something like this:
class MyClass {
protected:
MatrixType m_11, m_12;
double compute_elements_m11(int i, int j, double x);
double compute_elements_m12(int i, int j, double x);
void compute_matrix(double x, std::function<double(int, int, double) > f);
public:
void compute_m_11(double x) {compute_matrix(x, compute_elements_m11);};
void compute_m_12(double x) {compute_matrix(x, compute_elements_m12);};
MatrixType& getMatrixType_11( return m_11 );
MatrixType& getMatrixType_12( return m_12 );
}
I've looked at the top answers c++ to Visitor pattern and to pointers to member functions; but I still cannot get how the following (rather simple) scenario should be designed.
In a basic example, I want to have an optimizer class. Given a member function of another class, it find some optimal value. Something like this:
class Optimizer{
public:
typedef double (*Func1d)(double);
typedef double (*Func2d)(double,double);
void Optimize1d(Func1d* f1Ptr, double& x);
void Optimize2d(Func2d* f2Ptr, double& x, double& y);
};
and two example classes:
class A {
double A1d(double x){return x;}
};
class B{
double B2d(double x, double y){return x+y;}
};
and the main function, which I would like to be able to use as follows:
void main()
{
Optimizer opt;
double xA_opt, xB_opt, yB_opt;
opt.Optimize1d(&A::A1d,xA_opt);
opt.Optimize2d(&B::B2d, xB_opt, yB_opt);
}
But still, I can't get it to work. I don't want the optimizer to directly hold pointers to objects of type A and B; because then he needs to be familiar with these objects.
I hope this question makes sense. Thanks!
The problem is that typedef double (*Func1d)(double); is not a member-function-pointer but just a plain function-pointer.
If you used a real member-function-pointer, the function would also have to have an instance of A or B which you say you don't want.
If you can't make A1d and B2d static the other options are to make your Optimize1d and Optimize2d template functions taking a templated functor:
template<typename F>
void Optimize1d(F f1, double& x);
template<typename F>
void Optimize2d(F f2, double& x, double& y);
or a std::function:
void Optimize1d(std::function<double(double)> f1, double& x);
void Optimize2d(std::function<double(double, double)> f2, double& x, double& y);
Both can be called with a lambda capturing an instance of A or B:
A a;
B b;
opt.Optimize1d([&a](double x){return a.A1d(x); }, xA_opt);
opt.Optimize2d([&b](double x, double y){return b.B2d(x, y); }, xB_opt, yB_opt);
Edit:
If you don't have C++11 you could define your own functor using a class which defines an operator() instead of a lambda. The class will have to store a pointer or reference to an instance of A or B in a member variable:
struct A1d {
A* a;
A1d(A& a) : a(&a) {}
double operator()(double x) { return a->A1d(x); }
};
You can then construct an instance of this class and pass it to the templated optimize functions:
A1d a1d(a);
opt.Optimize1d(a1d,xA_opt);
Live demo.
perhaps you could even make your A or B classes functors themselves by adding an operator() function to them?
The problem in the above code is that in C++, pointer-to-member functions are a distinct type, incompatible with "regular" function pointers.
This typedef
typedef double (*Func1d)(double);
is legal in both C and C++ code, and you can use C-style "free" functions with this type.
But at this line in your main function:
opt.Optimize1d(&A::A1d,xA_opt);
you are trying to pass a pointer to member function as a Func1d and that can't be done. For one thing, you can't invoke a pointer to member function without a pointer to an object of that type as well, and you would have to pass that also.
The simplest thing is to include header <functional> and use std::function<double(double)> for this. (Assuming you have C++11, otherwise you could use boost::function.)
There are other things you could do like use virtual member dispatch as suggested in comments. (IMO that's a little less elegant.)
You could also make the optimize functions be template functions, and accept an object of the templated type etc. etc. But really std::function is the way to go here, it will handle all those details for you.
I suppose this is a very simple question to advanced C++ programmers, but I'm not one, so:
Using C++ 11, what's an elegant way to implement a std::map that uses a scoped enum as a key and takes mathematical functions that have varying signatures as values:
Simple example - could be any numeric type or any number of function args, but these are typical for my use case:
enum class FUNCS
{
DOUBLE_FUNC1, DOUBLE_FUNC2, INT_FUNC3, INT_FUNC4
};
Some functions:
double f1( int a, int b, double d);
double f2( int a, int b, int c, int d);
int f3( int a, double d, int c, double e);
int f4( int a, double d, int c);
The functionality I seek is a std::map that works like this:
Initialize the map:
mMAP[FUNCS::DOUBLE_FUNC1]=f1;
mMAP[FUNCS::DOUBLE_FUNC2]=f2;
mMAP[FUNCS::INT_FUNC3]=f3;
mMAP[FUNCS::INT_FUNC4]=f4;
Use the map:
mMAP[FUNCS::DOUBLE_FUNC1](a,b,d);
mMAP[FUNCS::INT_FUNC3](a,d,c,e);
A compromise that would involve some type casting could use functions with varying arguments that all return double:
double f1( int a, int b, double d);
double f2( int a, int b, int c, int d);
double f3( int a, double d, int c, double e);
double f4( int a, double d, int c);
How can I can declare a map that will give me this functionality? I understand that I probably cannot map those functions directly to those keys - I will need some sort of abstraction/indirection to accomplish this goal, and I believe that using variadic functions/templates this can be accomplished, see Variadic arguments and Parameter pack, but I'm really not clear on how to do get this working.
Meanwhile I have implemented a cludgy solution using a function pointer type that takes a std::tuple containing a series of values of all possible types as an argument with references for the results, and then in each fuction mapped, I use the appropriate members of the tuple. UGLY!
My goal here is to send data from these various functions to a charting library which generates charts using data of type boost::any A GUI driven state machine will call the appropriate function through the map based on the enum value represented in the state machine, and generate a chart based on data from that function.
C++ is a statically typed language.
The only way you could do this would be to have all the functions use a common signature, for instance:
struct F1Data { double result; int a; int b; double d; };
struct F2Data { double result; int a, b, c, d; };
struct F3Data { int result; int a, b; double c; };
struct F4Data { int result; double a, b; int c; };
void f1(void* data);
void f2(void* data);
void f3(void* data);
void f4(void* data);
Then within each the functions, you can cast data to the right type and work on the values from there.
That's as close as you'll be able to get. You can mask it with libraries like tuple or any but it will always boil down to making a shared signature across all of the functions.
Since all functions have different signatures, it is not possible.
Since all functions have different types, you can't even use some kind of type erasure.
I was wondering if in C++ it was possible to get a function taking (n-1) arguments out of a function taking n arguments by setting the value for the nth argument to some value (to be determined at runtime)?
E.g. I would like to do something like the following:
float foo(float a, float b, float c){
// do some stuff
}
float bar(float x, float y, float f(float q, float r)){
return f(x,y);
}
int main(){
double (*function)(float, float);
float some_value;
// somehow determine some_value, e.g. read from stdin.
// Now I would like to set function something along the lines of:
function = foo( . , . , some_value)
return bar(123, 456, function);
}
Conceptually, foo is a family of functions indexed by c, i.e. a family of functions foo_c (float a, float b) (read "foo_c" as "foo subscript c" here), and I want to pass foo_c respectively a pointer to it as an argument to bar.
Is this possible at all in C++?
To the best of my knowledge, this isn't possible with function pointers as above. Is there any other way of doing something like this?
I briefly considered making foo a function template, but this won't work as I want to set it's third argument at runtime.
The obvious solution is of course to amend bar so as to take type float f(float q, float r, float t) as its third argument, but this would make the code a lot less reusable (and seems less elegant). I will want to pass other functions to bar as well, some of which will only take two arguments, more than three, or arguments of different types, which I somehow need to set to a fixed value before passing them to bar.
I haven't quite been able to figure out if I could make bar a template function in this case, along the lines of template <typename T, typename S> float bar(float x, float y, T f(float a, float b, S param), S parameters), and then call it using something like bar <double *(float, float, float), float> (123, 456, function, parameters). Would anything along these lines work at all?
You cannot do it with function pointers, however, it can be done with function objects. I recommend you look at Boost.Bind if you're using C++03. If you're using C++11, std::bind is part of the standard and works the same way. C++11 also introduces built-in lambdas which do what you're attempting.
For storing the result of bind or a lambda, you can use Boost.Function in C++03 or std::function in C++11.
This example is how you would do it in C++03.
float foo(float a, float b, float c){
// do some stuff
}
float bar(float x, float y, boost::function<float(float,float)> f){
return f(x,y);
}
int main(){
boost::function<float(float,float)> func;
float some_value;
// somehow determine some_value, e.g. read from stdin.
// Now I would like to set function something along the lines of:
func= boost::bind(foo, _1, _2, some_value);
return bar(123, 456, func);
}
In C++11, you could use the standardized versions of bind and function, or you could use the lambda feature:
float foo(float a, float b, float c){
// do some stuff
}
float bar(float x, float y, std::function<float(float,float)> f){
return f(x,y);
}
int main(){
std::function<float(float,float)> func;
float some_value;
// somehow determine some_value, e.g. read from stdin.
// Now I would like to set function something along the lines of:
func= [some_value](float x, float y) { return foo(x,y,some_value); };
return bar(123, 456, func);
}
You can't do it with function pointers like that, but you can do it with function-like objects. C++11 gives you std::bind and std::function (and also lambdas, but I don't know enough about them to give an example); in C++03, boost::bind and boost::function are very similar.
float foo(float a, float b, float c){
// do some stuff
}
float bar(float x, float y, function<float(float, float)> f){
return f(x,y);
}
int main(){
float some_value;
// somehow determine some_value, e.g. read from stdin.
return bar(123, 456, bind(foo,_1,_2,some_value));
}