For a struct point{float x,y,z;}, i want to define many functions, in each function, i do the same thing to x, y and z. For example, float size = 1 * x*y*z, float edge = 0+x+y+z...
So I'm wondering that, i could write a macro, or something, like
#define forxyz(codes) ???????
that when i write
forxyz(res=res+d;)
it calls res=res+x; res=res+y;res=res+z;
Urrr, lemme make it more clear. I have about 20 functions, each one is called for only one time, so I don't want to attach them to the struct. Moreover, it's not as simple as '+'. for example, i might have
x_in_middle(point a, point b, point c, float d){
if(b.x<a.x && a.x<c.x){
if(d>0) return a.x;
if(d<0) return a.x*a.x;
if(d==0) return 0;
}
}
and I'm finding a way to not to write
if(b.x<a.x && a.x<c.x){
if(d>0) return a.x;
if(d<0) return a.x*a.x;
if(d=0) return 0;
}
three times!
In this case res=res+d is pretty simple, but in my case it might be several lines of codes...and sometime i would want to call set_x, set_y, set_z functions...
So far, the best idea i could have is to make res=res+d another macro, namely
#define add(d) res=res+d
and then
add(x);
add(y);
add(z);
But this would obviously create too much macros, and i think it's not elegant...
A simple method is to write a freestanding function that takes points as parameters:
point add(const point& a, const point& b)
{
point c;
c.x = a.x + b.x;
c.y = a.y + b.y;
c.z = a.z + b.z;
return c;
}
You would use this like:
point a, b, c;
//...
c = add(a, b);
You could also overload operator +:
point operator+(const point& a, const point& b)
{
point c;
c.x = a.x + b.x;
c.y = a.y + b.y;
c.z = a.z + b.z;
return c;
}
Your usage may look like this:
point a, b, c;
//...
c = a + b;
This is the answer that answers the macro part and I would advise to provide operators overloads if possible and not to use macros in C++.
So first create your own small overloaded foreach macro that will apply a function on each argument:
#define M_FOREACH_1(func,_1) \
func(_1)
#define M_FOREACH_2(func,_1,_2) \
M_FOREACH_1(func,_1)func(_2)
#define M_FOREACH_3(func,_1,_2,_3) \
M_FOREACH_2(func,_1,_2)func(_3)
/// etc.
#define M_FOREACH_N(_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...) \
M_FOREACH_##N
#define M_FOREACH(func, ...) \
M_FOREACH_N(__VA_ARGS__,9,8,7,6,5,4,3,2,1)(func, __VA_ARGS__)
Then let's abstract it for some argument braced list that needs to be escaped, for verbosity:
#define M_FOREACHLIST_ESCAPE(...) \
__VA_ARGS__
#define M_FOREACHLIST_IN(func, ...) \
M_FOREACH(func, __VA_ARGS__)
#define M_FOREACHLIST(func, list) \
M_FOREACHLIST_IN(func, M_FOREACHLIST_ESCAPE list)
// now we can
// M_FOREACHLIST(some_macro, (x, y, z))
After that it's typicall to define a function for expansion, apply it foreach some arguments list:
#define list() (x, y, z)
#define add(arg) res = res + arg;
M_FOREACHLIST(add, list())
// generates res = res + x;res = res + y;res = res + z;
#undef add
#define sub(arg) res = res - arg;
M_FOREACHLIST(sub, list())
// generates res = res - x;res = res - y;res = res - z;
#undef sub
// etc.
and I'm finding a way to not to write ... three times!
Pass member pointer to the function...
float generic_in_middle(point a, point b, point c, float d, float point::* mp){
if (b.*mp < a.*mp && a.*mp < c.*mp){
if (d > 0) return a.*mp;
if (d < 0) return a.*mp * a.*mp;
if (d == 0) return 0;
}
// TODO: add code here so that function returns something
}
float x_in_middle(point a, point b, point c, float d) {
return generic_in_middle(a, b, c, d, &point::x);
}
// etc.
Delegate axis-specific public API functions to a common helper function or operator
As the three data members are all of the same type, and you want to implement re-usable, say, arithmetic operations applied on a single one of them, you could wrap the common arithmetic functionality in a private helper, and delegate publically expose axis-specific functions to the helper.
#include <iostream>
struct Point {
Point(float x, float y, float z) : x_(x), y_(y), z_(z) {}
float addX(const float a) const { return add(x_, a); }
float addY(const float a) const { return add(y_, a); }
float addZ(const float a) const { return add(z_, a); }
private:
static float add(const float lhs, const float rhs) {
// Long complex arithmetic code.
return lhs + rhs;
}
float x_;
float y_;
float z_;
};
int main() {
const Point p{1., 2., 3.};
std::cout << p.addY(0.5); // 2.5
return 0;
}
You could likewise resort to implementing the helper as a member function template with a a single pointer to member function non-type template parameter, and delegate calls to this function.
#include <iostream>
struct Point {
Point(float x, float y, float z) : x_(x), y_(y), z_(z) {}
float addX(const float a) const { return add<&Point::x_>(a); }
float addY(const float a) const { return add<&Point::y_>(a); }
float addZ(const float a) const { return add<&Point::z_>(a); }
private:
template <float Point::* lhs>
float add(const float rhs) const {
// Long complex arithmetic code
// on lhs.
return rhs + (this->*lhs);
}
float x_;
float y_;
float z_;
};
int main() {
const Point p{1., 2., 3.};
std::cout << p.addY(0.5); // 2.5
return 0;
}
(C++20) Looping over a known number of public members: structured bindings in a range-based for loop initialization statement
Another alternative, as a simple POD-type such as a point data type is likely to have data members with public access modifiers, as of C++20 we may combine structured bindings with range-based for loop initialization statements (the latter is a C++20 feature):
Grammar
for ( init-statement(optional) range-declaration : range-expression ) ...
Specifically, using structured bindings as the init-statement in a range-based for loop:
#include <iostream>
struct Point {
float x;
float y;
float z;
};
float add(const float lhs, const float rhs) {
// Long complex arithmetic code.
return lhs + rhs;
}
int main() {
const Point p{1., 2., 3.};
// For all members, do ...
for (auto [x, y, z] = p; auto e : {x, y, z}) {
std::cout << add(0.5, e) << " ";
} // 1.5 2.5 3.5
return 0;
}
I am getting a compilation error saying " ‘PointType’ is not a member of ‘Point’ " I do not know what I need to implement in my code. Been thinking for a while now. I've tried adjusting the codes here and there a few times. But could not think of a solution for this. I'm a little confused by what "Point point(Point::PointType(x, y), depth);" in the main() wants. What exactly is PointType(x,y)? Can anyone enlighten me with what I should do? Would appreciate anyone's help on this. Side Note: Main() can't be touched. Thanks!
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
struct PointType
{
float x;
float y;
PointType(const float x1, const float y1) :x(x1),y(y1){}
};
class Object
{
private:
float d;
PointType * pt;
public:
Object(float n) : d(n){}
float depth() const
{
return d;
}
};
class Point :public Object
{
private:
PointType mpoint;
public:
Point(const PointType& pt, float& y1) : mpoint(pt), Object(y1) {}
virtual ~Point();
};
Main file:
const float EPSILON = 1e-5f;
bool is_near(float x, float y)
{
return std::abs(x - y) < EPSILON;
}
float frand()
{
return 10.0f * float(rand()) / float(RAND_MAX);
}
int main()
{
srand(unsigned(time(0)));
int count = 0;
int max_count = 0;
float x = frand();
float y = frand();
float depth = frand();
Point point(Point::PointType(x, y), depth);
if (is_near(point.depth(), depth))
{
++count;
}
else
{
std::cout << " - Point::depth test failed" << std::endl;
}
++max_count;
}
You've got a set circular declarations that can't be resolved if you can't change main(). You currently have PointType as a struct outside of the Point class. That's fine, but then you need to change the line in main() from:
Point point(Point::PointType(x, y), depth);
to:
Point point(PointType(x, y), depth);
But if you can't do that, then you can't ever compile this because Point is a subclass of Object, but Object requires a Point::PointType which can't have been defined yet. In order to have PointType be owned by Point, you need to declare it like this:
class Point :public Object
{
struct PointType
{
float x;
float y;
PointType(const float x1, const float y1) :x(x1),y(y1){}
};
private:
PointType mpoint;
public:
Point(const PointType& pt, float& y1) : mpoint(pt), Object(y1) {}
virtual ~Point();
};
But once you put PointType into Point, you can't declare any member of Object to have a type of Point::PointType because Point inherits from Object.
You could declare Object::pt to be a void* but that throws away type information which is dangerous.
I need to send a class member function 'curve' to another function 'fun', but I get errors during compilation. How to code this correctly?
Using address '&' results in C2276, without using it - C3867.
class Test
{
public:
double v;
double curve(double x)
{
return x + v;
}
Test(double z)
{
v = z;
}
};
double fun(double(*f)(double), double x)
{
return f(x);
}
void main()
{
Test d(2.0);
double r = fun(&d.curve, 3.0);
}
curve is a member function of Test class so you need to have an instance of Test on which curve can be called.
You can change fun to take as first parameter pointer to member function and as second param pass a reference to Test instance, the result code may look like:
class Test {
public:
double v;
double curve(double x) {
return x + v;
}
Test(double z) {
v = z;
}
};
double fun( double(Test::*f)(double) , Test& obj, double x) {
return (obj.*f)(x);
}
int main()
{
Test d(2.0);
double r = fun(&Test::curve, d, 3.0);
}
If you can change the fun signature, the answer of rafix07 is perfect.
If you don't want to change the number of parameters of fun, you probably want to write something like that:
double fun(double(*f)(double), double x)
{
return f(x);
}
int main() // not void
{
Test d(2.0);
double r = fun([d](double double_){ return d.curve(double_); }, 3.0);
std::cout << r;
}
Sadly it doesn't work because a lambda can be stored in a function pointer only if it doesn't use a capture.
So you have 2 solutions:
1) the template
// Must be in .hpp
template <class T>
double fun(T f, double x)
{
return f(x);
}
int main() // not void
{
Test d(2.0);
double r = fun([d](double double_) mutable { return d.curve(double_); }, 3.0);
}
2) the std::function
#include <functional>
double fun(std::function<double(double)> f, double x)
{
return f(x);
}
Note: you have to use mutable because double curve(double x) is not const, I think it should be.
General question :
If there are two objects A and B with respective functions f_A(arg list) and f_B(arg list).
What's the best way to create an object C with a function compounded of f_A(...) and f_B(...) ?
for example : f_C() = f_A() + f_B() or f_C() = f_A(f_B())
Is it possible to overload the "+" operator such that we can create the object C doing something like that ?
auto object_c = object_a + object_b
Here is a sample of my code :
class GaussianKernel : public Kernel {
public:
GaussianKernel(double sigma) : m_sigma(sigma), m_scale(1) {}
double covarianceFunction(
double X,
double Y
)
{
double result;
result = m_scale * exp(-norm(X - Y) / (m_sigma*m_sigma));
return result;
}
GaussianKernel operator+(const GaussianKernel& b) {
/*Here I would like to overload the + operator such that
I can create a kernel from two others kernels,
I mean with a covariance function compound of the previous ones
*/
}
private:
double m_sigma;
double m_scale;
};
Thanks you.
Given two methods f_A and f_B you can get f_C returning the sum of the others by using for example a lambda:
auto f_C = [](/*param*/){ return f_A(/*param*/) + f_B(/*param*/); };
auto sum_result = f_C(param);
To get the compound method it would be this:
auto f_C = [](/*param*/){ return f_B( f_A(/*param*/)); };
auto compound_result = f_C(param);
PS: I know that this is not directly applicable to your example, still trying to find out what exactly you want to do.
I would start with prototype solution like this:
class FooKernel : public Kernel {
public:
FooKernel (std::function<double(double, double)> fun) : fun_(fun) {}
double covarianceFunction(
double X,
double Y
) const {
return fun_(X, Y);
}
template<class T>
auto operator+(const T &b) const {
return FooKernel([b, this](double X, double Y){
return this->covarianceFunction(X, Y) + b.covarianceFunction(X, Y);
});
}
private:
std::function<double(double, double)> fun_;
};
class GaussianKernel : public Kernel {
public:
GaussianKernel(double sigma) : m_sigma(sigma), m_scale(1) {}
double covarianceFunction(
double X,
double Y
) const
{
double result;
result = m_scale * exp(-norm(X - Y) / (m_sigma*m_sigma));
return result;
}
template<class T>
auto operator+(const T &b) const {
return FooKernel([b, this](double X, double Y){
return this->covarianceFunction(X, Y) + b.covarianceFunction(X, Y);
});
}
private:
double m_sigma;
double m_scale;
};
No longer lambdas are used, but now uses Your function as You wished.
Later on I would try to remove the std::function as it may have quite big performance impact. Instead I would make the FooKernel a class template, that stores callable by value.
I would suggest another subclass of Kernel:
class CompoundGaussianKernel : public Kernel {
public:
CompoundGaussianKernel(GaussianKernel const& kernel1, GaussianKernel const& kernel2)
: m_kernel1(kernel1), m_kernel2(kernel2)
{}
double covarianceFunction(double X, double Y)
{
return m_kernel1.covarianceFunction(X, Y) + m_kernel2.covarianceFunction(X, Y);
// or any other composition than "+"
}
private:
GaussianKernel m_kernel1;
GaussianKernel m_kernel2;
};
I recommend not to define operator+ inside of a class but as a free function.
CompoundGaussianKernel operator+(GaussianKernel const& kernel1, GaussianKernel const& kernel2)
{
return CompoundGaussianKernel(kernel1, kernel2);
}
I have two functors:
class SFunctor {
public:
SFunctor(double a) { _a = a; }
double operator() (double t) { return _a * sin(t); }
private:
double _a;
};
class CFunctor {
public:
CFunctor(double b) { _b = b; }
double operator() (double t) { return _b * cos(t); }
private:
double _b;
};
I want to pass one or the other of these functions to another function:
double squarer(double x, ??______?? func) {
double y = func(x);
return y * y;
}
In my main program I want to make a call like this:
CFunctor sine(2.);
SFunctor cosine(4.);
double x= 0.5;
double s = squarer(x, sine);
double c = squarer(x, cosine);
How do I specify the function fund, that is what goes in front of it in place of ??_?? ?
You can simply do it with templates
template <class F>
double squarer(double x, F& func) {
double y = func(x);
return y * y;
}
I'm not knocking on the above template answer. In fact, it may be the better choice of the two, but I wanted to point out that this can be done with polymorphism as well. For example...
#include <math.h>
#include <iostream>
using std::cout;
using std::endl;
class BaseFunctor {
public:
virtual double operator() (double t) = 0;
protected:
BaseFunc() {}
};
class SFunctor : public BaseFunctor {
public:
SFunctor(double a) { _a = a; }
double operator() (double t) { return _a * sin(t); }
private:
double _a;
};
class CFunctor : public BaseFunctor {
public:
CFunctor(double b) { _b = b; }
double operator() (double t) { return _b * cos(t); }
private:
double _b;
};
double squarer(double x, BaseFunctor& func) {
double y = func(x);
return y * y;
}
int main() {
SFunctor sine(.2);
CFunctor cosine(.4);
double x = .5;
cout << squarer(x,sine) << endl;
cout << squarer(x,cosine) << endl;
}
I ensured that this was a full working demo, so you can just copy it to test it. You will indeed observe two different numbers print to the terminal, thus proving that polymorphism can be used with functors. Again, I'm not saying this is better than the template answer, I just wanted to point out that it isn't the only answer. Even though the question has been answered, I hope this helps inform anyone who wants to be informed.