Doing conditional replacement using c++ macro? - c++

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;
}

Related

How to update multiple fields of a struct simultaneously?

Let's say I have a struct
struct Vector3 {
float x;
float y;
float z;
};
Note that sizeof(Vector3) must remain the same.
EDIT: I am interested in solutions without setters.
Not let's create an instance of that struct Vector3 pos . How can I implement my struct so I can have something like this pos.xy = 10 // updates x and y or pos.yz = 20 // updates y and z or pos.xz = 30 // updates x and z?
Here is a solution that has the desired syntax, and doesn't increase the size of the class. It is technically correct, but rather convoluted:
union Vector3 {
struct {
float x, y, z;
auto& operator=(float f) { x = f; return *this; }
operator float&() & { return x; }
operator const float&() const & { return x; }
operator float () && { return x; }
float* operator&() { return &x; }
} x;
struct {
float x, y, z;
auto& operator=(float f) { y = f; return *this; }
operator float&() & { return y; }
operator const float&() const & { return y; }
operator float () && { return y; }
float* operator&() { return &y; }
} y;
struct {
float x, y, z;
auto& operator=(float f) { z = f; return *this; }
operator float&() & { return z; }
operator const float&() const & { return z; }
operator float () && { return z; }
float* operator&() { return &z; }
} z;
struct {
float x, y, z;
auto& operator=(float f) { x = y = f; return *this; }
} xy;
struct {
float x, y, z;
auto& operator=(float f) { y = z = f; return *this; }
} yz;
struct {
float x, y, z;
auto& operator=(float f) { z = x = f; return *this; }
} zx;
};
Another which relies on owner_of implemented here: https://gist.github.com/xymopen/352cbb55ddc2a767ed7c5999cfed4d31 which probably depends on some technically implementation specific (possibly undefined) behaviour:
struct Vector3 {
float x;
float y;
float z;
[[no_unique_address]]
struct {
auto& operator=(float f) {
Vector3* v = owner_of(this, &Vector3::xy);
v->x = v->y = f;
return *this;
}
} xy;
[[no_unique_address]]
struct {
auto& operator=(float f) {
Vector3* v = owner_of(this, &Vector3::yz);
v->y = v->z = f;
return *this;
}
} yz;
[[no_unique_address]]
struct {
auto& operator=(float f) {
Vector3* v = owner_of(this, &Vector3::zx);
v->z = v->x = f;
return *this;
}
} zx;
[[no_unique_address]]
struct {
auto& operator=(float f) {
Vector3* v = owner_of(this, &Vector3::zx);
v->x = v->y = v->z = f;
return *this;
}
} xyz;
};
The simple way is to provide setters for the combinations you want to set:
struct Vector3 {
float x = 0;
float y = 0;
float z = 0;
void set_xy(float v) {
x = v;
y = v;
}
};
int main(){
Vector3 pos;
pos.set_xy(42);
}
And if you need sizeof(Vector3) to stay the same, thats the only way.
Just "for fun" this is how you can get pos.set_xy = 20; literally:
struct two_setter {
float& one;
float& two;
void operator=(float v){
one = v;
two = v;
}
};
struct Vector3 {
float x = 0;
float y = 0;
float z = 0;
two_setter set_xy{x,y};
};
int main(){
Vector3 pos;
pos.set_xy = 42;
}
However, it has severe downsides. First it can have almost twice the size of the original Vector3. Moreover, because the two_setter stores references, Vector3 cannot be copied. If it would store pointers, copying would be possible, but then even more code would be required to get it right.
Alternatively it is possible to provide a xy method that returns a proxy that assigns the two members. But I am not going into detail, because pos.xy() = 3; looks really odd, has no advantage to pos.xy(3) and you really should provide a setter (or just rely on the user making two assignments when they want to make two assignments ;).
TL;DR Use a method instead of trying to get a syntax that C++ does not support out of the box.
It is possible to create an empty struct inside Vector3 with an operator=() that sets the variables of the outer struct. Of course for a variable to really take no space itself, you have to use [[no_unique_address]], which is only available since C++20. But here is an example of how it might work:
struct Vector3 {
[[no_unique_address]] struct {
auto &operator=(float val) {
Vector3 *self = (Vector3 *)(this);
self->x = val;
self->y = val;
return *this;
}
} xy;
// Add similar code for xz and yz
float x;
float y;
float z;
};
See it running on godbolt.org.
Since your type is standard-layout, I think the only legal way to do this, as per the C++ standard, is with a union that contains sub-objects with custom operator= definitions.
With a union, you're allowed to view the common-initial sequence of the active member, provided all types are standard-layout types. So if we carefully craft an object that shares the same common members (e.g. 3 float objects in the same order), then we can "swizzle" between them without violating strict-aliasing.
For us to accomplish this, we will need to create a bunch of members that all have the same data in the same order, in standard-layout type.
As a simple example, lets create a basic proxy type:
template <int...Idx>
class Vector3Proxy
{
public:
// ...
template <int...UIdx,
typename = std::enable_if_t<(sizeof...(Idx)==sizeof...(UIdx))>>
auto operator=(const Vector3Proxy<UIdx...>& other) -> Vector3Proxy&
{
((m_data[Idx] = other.m_data[UIdx]),...);
return (*this);
}
auto operator=(float x) -> Vector3Proxy&
{
((m_data[Idx] = x),...);
return (*this);
}
// ...
private:
float m_data[3];
template <int...> friend class Vector3Proxy;
};
In this example, not all members of m_data are used -- but they exist so that the "common-initial sequence" requirement is satisfied, which will allow us to view it through other standard-layout types within the union.
This can be built up as much as you need; float conversion for single-component operators, support for arithmetic, etc.
With a type like this, we can now build a Vector3 objects out of these proxy types
struct Vector3
{
union {
float _storage[3]; // for easy initialization
Vector3Proxy<0> x;
Vector3Proxy<1> y;
Vector3Proxy<2> z;
Vector3Proxy<0,1> xy;
Vector3Proxy<1,2> yz;
Vector3Proxy<0,2> xz;
// ...
};
};
Then the type can easily be used to assign to multiple values at once:
Vector3 x = {1,2,3};
x.xy = 5;
Or to assign components of one part to another:
Vector3 a = {1,2,3};
Vector3 b = {4,5,6};
a.xy = b.yz; // produces {5,6,3}
Live Example
This solution also ensures that sizeof(Vector3) does not change, since all proxy objects are the same size.
Note: It's not valid in C++ to use a union with anonymous structs, though some compilers support it. So although it might be tempting to rewrite this like:
union {
struct {
float x;
float y;
float z;
}; // invalid, since this is anonymous
struct {
...
} xy;
}
This is not valid in standard C++, and would not be a portable solution.
How can I implement my struct so I can have something like this pos.xy = 10 // updates x and y or pos.yz = 20 // updates y and z or pos.xz = 30 // updates x and z?
Just add the necessary class member functions to do this:
struct Vector3 {
float x;
float y;
float z;
void update_xy(float value) { x = y = value; }
void update_yz(float value) { y = z = value; }
void update_xz(float value) { x = z = value; }
};

Implement hash for custom class C++

I have a circle defined like so:
class Circle {
public:
int x;
int y;
int r;
Circle() : x(0), y(0), r(0) {}
Circle(int x, int y, int r) {
this->x = x;
this->y = y;
this->r = r;
}
double area() {
return PI * pow(r, 2);
}
};
I want to be able to add it to a set, based on the hash of its center (x and y)
What's the correct and idiomatic way of doing this in C++ 11?
My question is two-fold
(1) Is there a way I can ask C++ to hash it for me? In Kotlin, there is the notion of a dataclass which automatically hashes the class attributes. I am looking for something similar.
(2) If not, how do I hash it myself, and relatedly - what are operators I need to overload?
I want to be able to add it to a set, based on the hash of its center (x and y)
If you wan't to put your circle in the std::set, you don't need to provide a hash function. You need to provide it only if you'd like to use std::unordered_set or any other unordered associative container (more info in hash).
As it goes for the most idiomatic way of implementation, I would go with something like this (taken from the std::hash example):
#include <cmath>
#include <unordered_set>
#include <set>
class Circle {
public:
int x;
int y;
int r;
Circle() : x(0), y(0), r(0) {}
Circle(int x, int y, int r) {
this->x = x;
this->y = y;
this->r = r;
}
double area() {
return 3.1415 * pow(r, 2);
}
};
bool operator==(const Circle& lhs, const Circle& rhs) {
return lhs.x == rhs.x && lhs.y == rhs.y;
}
template<> struct std::hash<Circle> {
std::size_t operator()(Circle const& s) const noexcept {
std::size_t h1 = std::hash<int>{}(s.x);
std::size_t h2 = std::hash<int>{}(s.y);
return h1 ^ (h2 << 1); // or use boost::hash_combine (see Discussion) https://en.cppreference.com/w/Talk:cpp/utility/hash
}
};
int main() {
std::unordered_set<Circle> circles;
return 0;
}
Link to example
EDIT:
(1) Is there a way I can ask C++ to hash it for me? In Kotlin, there is the notion of a dataclass which automatically hashes the class attributes. I am looking for something similar.
There is hash function for the basic types (list is on std::hash). You need to provide hashing function for your custom type. You can take an inspiration from the cppreference or create an own hashing function.

Is there a way to compound functions in C++?

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);
}

C++ Include Unitialisable Objects [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Here is my main code since it is seems that idea is not really coming across. hope this clarifies things. it consists of neural net activation functions
activation.cpp
typedef struct
{
virtual float operator() (float x) const = 0;
virtual float gradient (float x, float g) const = 0;
} activation;
struct sigmoid : activation
{
float operator() (float x)
{ return 1.f / (1.f + expf(-x)); }
float gradient(float x, float g)
{ float s = (*this)(x); return g * s * (1.f - s); }
};
struct relu : activation
{
float operator() (float x)
{ return x; }
float gradient(float x, float g)
{ return g; }
};
i want these functor objects to be callable as they are upon include as they will always be the same...
EG
main.cpp
#include "activation.cpp"
int main() { cout << sigmoid(0) << sigmoid.gradient(0) << endl; }
prints
0.50.25
To call a functor via A(3), then A has to be the name of an variable, not the type. Which means A has to be either a instance of the functor, which ends up complicated because the functor type is public in which case you have to forbid others from constructing and copying and taking addresses and all that. Alternatively: make A a regular function.
functors.h
int A(int x);
functors.cpp
struct AFunctor {
int operator()(int x) const {return 3*x;} ;
};
int A(int x) {
static AFunctor a;
return a(x);
}
main.cpp
#include "functors.h"
int main()
{cout << A(3) << endl;}
As should be obvious at this point, there's literally no reason to have a singleton functor like this. Functors are usually stateful, or you can create them left and right, or both.
Since it's now clear that you definitely want singleton functors, this would be the way to go I guess.
functors.h
struct activation
{
virtual float operator() (float x) const = 0;
virtual float gradient (float x, float g) const = 0;
};
struct sigmoidFunctor : activation
{
float operator() (float x);
float gradient(float x, float g);
static sigmoidFunctor& get();
private
sigmoidFunctor()=default;
sigmoidFunctor(const sigmoidFunctor&)=delete;
};
extern sigmoidFunctor& sigmoid;
struct reluFunctor : activation
{
float operator() (float x);
float gradient(float x, float g);
static reluFunctor& get();
private
reluFunctor()=default;
reluFunctor(const reluFunctor&)=delete;
};
extern reluFunctor& relu;
functors.cpp
float sigmoidFunctor::operator() (float x)
{ return 1.f / (1.f + expf(-x)); }
float sigmoidFunctor::gradient(float x, float g)
{ float s = (*this)(x); return g * s * (1.f - s); }
sigmoidFunctor& sigmoidFunctor::get() {
static sigmoidFunctor sigmoid;
return sigmoid;
}
sigmoidFunctor& sigmoid = sigmoidFunctor.get();
float reluFunctor::operator() (float x)
{ return x; }
float reluFunctor::gradient(float x, float g)
{ return g; }
reluFunctor& reluFunctorFunctor::get() {
static reluFunctor relu;
return relu;
}
reluFunctor& relu = reluFunctor.get();
As evidenced by the vast increase in complexity, I strongly urge you to reconsider. Usually, singletons just make a mess of everything.

How can I build this typ of class interface

I am interested in trying something where I create a custom type and then access to its members using dot semantics. For example:
Class A{ //simplified, omitting constructors and other methods
private:
float numbers[3];
public:
float x(){ return numbers[0]; }
float y(){ return numbers[1]; }
float z(){ return numbers[2]; }
}
So I can do something like this:
A a;
//do stuff to populate `numbers`
float x=a.x;
But I would also like to make the elements in numbers lvalues so I can do something like this:
A a;
a.y=5; //assigns 5 to numbers[1]
How can I do this setting method?
You can return a reference to allow assignment:
float & x(){ return numbers[0]; }
^
// usage
A a;
a.x() = 42;
You should also have a const overload, to allow read-only access to a const object:
float x() const {return numbers[0];}
^^^^^
// usage
A const a = something();
float x = a.x();
First. You made functions x, y and z but assigning them to float. This wouldn't work.
Second. Change these functions to return referencies:
class A{ //simplified, omitting constructors and other methods
private:
float numbers[3];
public:
float & x(){ return numbers[0]; }
float & y(){ return numbers[1]; }
float & z(){ return numbers[2]; }
};
...
A point;
float x = point.x();
point.x() = 42.0f;
There's another way: declare referencies as a members of class and initialize them in c-tor:
class A{ //simplified, omitting constructors and other methods
private:
float numbers[3];
public:
float & x;
float & y;
float & z;
A() : x( numbers[ 0 ] ), y( numbers[ 1 ] ), z( numbers[ 2 ] ) {}
};
...
A point;
float x = point.x;
point.x = 42.0f;
P.S. Pay an attention on comment, that gave #MikeSeymour
Not unless you actually have public variables named x, y and z.
Or you can return a reference and then do a.y() = 5