I have several different C++ structs and classes with fields of the same name, that I have to copy between frequently. I would like to do something like: (in bashy pseudocode)
struct S{double a;
double b;
double c;};
class C{public: void set_a(double a);
void set_b(double b);
void set_c(double c); };
S s; C c;
#FOR F in FIELDSOF(S)
c.set_${F}(${F});
#ENDFOR
Whether or not it a good idea, is there a way to abuse either the C++ preprocessor or C++ templates to achieve this? I use g++ and clang++.
I am already aware of templating engines like MAKO, and I'm also aware I could write a program to do code generation. If you must know, one of the things I would like to use this for is filling Google protobufs from C++ structs.
If you already have a Boost dependency, you can use BOOST_FUSION_ADAPT_STRUCT and use Fusion to iterate over the members. This also allows you to work with types, which is not possible in a pure preprocessor approach.
You also will need to map member functions to fusion sequences to make that more automatic.
All in all: Just write a constructor.
See this answer, which shows how to iterate over the members of a class. Then using those macros, the two classes can be reflectable like this:
struct S
{
REFLECTABLE
(
(double) a,
(double) b,
(double) c
)
};
class C
{
private:
REFLECTABLE
(
(double) a,
(double) b,
(double) c
)
public:
void set_a(double a);
void set_b(double b);
void set_c(double c);
};
Then to create a generic assignment, based on the name of the member variable:
struct assign_fields_visitor
{
template<class FieldData1, class FieldData2>
void operator()(FieldData1 fd1, FieldData2 fd2)
{
if (strcmp(fd1.name(), fd2.name()) == 0)
{
fd1.get() = fd2.get();
}
}
};
struct assign_fields
{
template<class X, class FieldData>
void operator()(X & x, FieldData f)
{
visit_each(x, boost::bind(assign_fields_visitor(), f, _1));
}
};
template<class L, class R>
void assign(L & lhs, const R& rhs)
{
visit_each(rhs, boost::bind(assign_fields(), boost::ref(lhs), _1));
}
Finally, it can be called like this:
S s; C c;
assign(c, s);
Related
When using virtual functions it is often convenient to use a single class template for both the base class and all derived classes. My question is: are classes defined this way treated any differently by the C++ compiler from the same classes defined without templates?
Here is an example of some classes created using templates:
template <typename T=void> struct Adder;
template <> struct Adder <void>
{
virtual double add(double a, double b)
{
return (a+b);
}
};
template <typename T> struct Adder : Adder <void>
{
virtual double add(double a, double b)
{
return ((T)a+(T)b);
}
};
using AdderBase = Adder <void>;
using AdderInt = Adder <int>;
using AdderFloat = Adder <float>;
using AdderDouble = Adder <double>;
int main(int argc, char* argv[])
{
AdderBase* addI = new AdderInt;
AdderBase* addF = new AdderFloat;
AdderBase* addD = new AdderDouble;
printf("addI = %18.1f\n", addI->add(11111111111111111.0, 1.0));
printf("addF = %18.1f\n", addF->add(11111111111111111.0, 1.0));
printf("addD = %18.1f\n", addD->add(11111111111111111.0, 1.0));
}
And here is an example of classes with the same functionality created without templates:
struct AdderBase
{
virtual double add(double a, double b)
{
return (a+b);
}
};
struct AdderInt : AdderBase
{
virtual double add(double a, double b)
{
return ((int)a+(int)b);
}
};
struct AdderFloat : AdderBase
{
virtual double add(double a, double b)
{
return ((float)a+(float)b);
}
};
struct AdderDouble : AdderBase
{
virtual double add(double a, double b)
{
return ((double)a+(double)b);
}
};
Does the compiler treat the classes AdderBase, AdderInt, AdderFloat or AdderDouble differently when they are defined in these two different ways?
An example of a difference might be a different order for overload resolution when the class is used as a parameter in an overloaded function.
The short answer is no.
In particular, I'd expect any reasonable compiler to generate identical code when you used either of your implementations of (say) AdderFloat. In fact, even well before the code generator starts looking at the code, both are doing to be reduced to identical intermediate representations.
There are cases where you can get different code from a template, but most often that's when you know there's a shortcut for some particular type, and write a specialization to let the compiler take advantage of that shortcut for that particular type.
Suppose I have some class, myClass, with a class constructor that takes 20 arguments, and simply assigns the passed values to class variables. Here's a smaller example, in case that's not clear
class myClass{
float a, b, c;
public:
myClass(float _a, float _b, float _c) : a(_a), b(_b), c(_c) {}
};
Is there a "cleaner" and/or more efficient way to do this? Perhaps a best practice? I've thought about simply passing a vector<float>, something like this:
class myClass{
vector<float> args;
public:
myClass(vector<float> _args){ args = _args; }
};
However, since I'm working with so many parameters, it later becomes confusing. For example, in some method I'm suddenly working with args[13] as opposed to something more descriptive, like numDays. I perform a lot of math on these numbers, so it's important that everything is very clear and concise.
You could write a class that has all these fields and just pass the class. Then, you can do yourClass.numDays and such.
A) The builder pattern
You can use the builder pattern. I am not going to strictly follow the pattern. For official details I refer you to the numerous available online resources on design patterns. The basic idea is that you enable the caller to write instead of
MonsterClass m{ a,b,c, ....... d,e,f };
the nicer
auto m = MonsterBuilder{}.set_a(a).set_b(b). .... set_f(f);
Advantage: Named parameters. C++ does not have named parameters, the builder pattern is a way to emulate them.
In your case it could be implemented as follows:
#include<iostream>
struct myClass{
float a, b, c;
myClass(float a, float b, float c) : a(a),b(b),c(c)
{} //^^ use the initializer list
void print(){ // added for testing
std::cout << a << " " << b << " " << c << "\n";
}
};
struct myClassBuilder {
float a;
float b;
float c;
myClassBuilder& set_a(float x){ a = x; return *this; }
myClassBuilder& set_b(float x){ b = x; return *this; }
myClassBuilder& set_c(float x){ c = x; return *this; }
operator myClass(){
return myClass(a,b,c);
}
myClass build() {
return *this;
}
};
int main() {
auto m1 = myClassBuilder{}.set_a(1).set_b(2).set_c(3).build();
m1.print();
myClass m2 = myClassBuilder{}.set_a(1).set_b(2).set_c(3);
m2.print();
}
The operator myClass allows to convert the builder to the actual object (by calling the constructor). The build method is needed when you want to use auto. Live Demo. Of course you should use meaningful names, a,b,c.. is just as good as using an array and index.
B) Fix the design
Consider the single responsibility principle. If your class does too much at once then you have more severe problems than getting the parameters into the constructor in a "nice" way. For example, it is impossible to get acceptable test coverage for something that takes 20+ inputs.
Suppose 3 of the 20+ parameters are numDays, numMonth and numYears. Then you should group them together:
struct date_counter {
int numDays;
int numMonth;
int numYears;
};
If on the other hand, the numbers are really just a bunch of numbers, then use a container.
I think your class has a lot of responsibilities. The SOLID's principles, more specifically, Single responsability's principle specify that one class should do only one thing and like you need a constructor which takes 20 arguments, i guess your class is an all-in-one.
This question already has answers here:
Iterating over a struct in C++
(8 answers)
Closed 1 year ago.
Is it possible in C++ to iterate through a Struct or Class to find all of its members? For example, if I have struct a, and class b:
struct a
{
int a;
int b;
int c;
}
class b
{
public:
int a;
int b;
private:
int c;
}
Would it be possible to loop them to say get a print statement saying "Struct a has int named a, b, c" or "Class b has int named a, b, c"
There are a couple of ways to do this, but you need to use some macros to either define or adapt the struct.
You can use the REFLECTABLE macro given in this answer to define the struct like this:
struct A
{
REFLECTABLE
(
(int) a,
(int) b,
(int) c
)
};
And then you can iterate over the fields and print each value like this:
struct print_visitor
{
template<class FieldData>
void operator()(FieldData f)
{
std::cout << f.name() << "=" << f.get() << std::endl;
}
};
template<class T>
void print_fields(T & x)
{
visit_each(x, print_visitor());
}
A x;
print_fields(x);
Another way is to adapt the struct as a fusion sequence (see the documentation). Here's an example:
struct A
{
int a;
int b;
int c;
};
BOOST_FUSION_ADAPT_STRUCT
(
A,
(int, a)
(int, b)
(int, c)
)
Then you can print the fields as well using this:
struct print_visitor
{
template<class Index, class C>
void operator()(Index, C & c)
{
std::cout << boost::fusion::extension::struct_member_name<C, Index::value>::call()
<< "="
<< boost:::fusion::at<Index>(c)
<< std::endl;
}
};
template<class C>
void print_fields(C & c)
{
typedef boost::mpl::range_c<int,0, boost::fusion::result_of::size<C>::type::value> range;
boost::mpl::for_each<range>(boost::bind<void>(print_visitor(), boost::ref(c), _1));
}
No, it's not possible, because there is no reflection in C++.
If you have members of the same type (as you do in your first specific example) that you want to both (a) have names, and (b) be iterable, then you can combine an array with an enum:
enum names { alice, bob, carl };
struct myStruct;
{
std::array<int, 3> members;
}
Then you can both
myStruct instance;
// iterate through them...
for (auto elem : instance.members)
{
// work with each element in sequence
}
// and call them by name, taking away the need to remember which element is the first, etc.
instance.members[bob] = 100;
Clearly not a general solution, but I've found this useful in my own work.
Provided your member variables are of the same type, you can do something like this that i stole from the GLM library:
class Point
{
Point();// you must re-implement the default constructor if you need one
union
{
struct
{
double x;
double y;
double z;
};
std::array<double, 3> components;
};
};
Admittedly this isn't the most elegant solution from a maintainability standpoint, manually keeping count of the number of variables you have is asking for trouble. However It will work without additional libraries or macros and is applicable in most situations that you'd want this behaviour.
Unions don't support automatically generated default constructors so you'll need to write one that tells the object how to initialise the union.
for (double component : point.components)
{
// do something
}
Assuming that all class members are of the same type, you may employ a C++17 feature called structured binding. Assuming that all members are public this would work:
struct SI
{
int x;
int y;
int z;
};
struct SD
{
double x;
double y;
double z;
};
template<typename T>
void print(const T &val)
{
const auto& [a, b, c] = val;
for (auto elem : {a, b, c})
{
std::cout << elem << " ";
}
std::cout << std::endl;
}
This would work with any struct that has exactly 3 public elements of the same (copyable) type. In case of non-public members the function must be a friend or a member. This approach however cannot be easily extented to arbitrary number of elements.
This is an improved version of QCTDevs answer:
class MyClass
{
union
{
struct Memberstruct
{
double test0;
double test1;
double test2;
} m;
array<double, sizeof( Memberstruct ) / sizeof( double )> memberarray;
};
bool test() { &(m.test1) == &(memberarray[1]); }
};
The requirement is still to have all the same datatypes, and you also need to implement the default Constructor, if needed.
It is improved in that you don't need to manually maintain the size of the array.
A drawback is an altered syntax in comparison to the class without this workaround.
I am looking for an optimal way of implementing the code common between subset of interface implemtations. To describe it concretely assume we have an interface P that is implemented by A, B and C. Again, assume A and B have certain common functionality (common code), B and C have certain common functionlity and similarly A and C have common functionality in the implementation of the interface. I understand that:
We can make intermediate class for each pair, containing the common functionality and then derive the classes from the intermediate classes, e.g., intermediate class AB implementing common code between A and B and BC for common code between B and C and then derive B from AB and BC.
Replicate the code for the classes in each pair
1 should theortically be the optimal solution, however, practially it can create a huge mess because actually I don't just have 3 classes implementing the interface but a large number of them. Moreover, the common functionalities are not just between pairs but large subsets of the classes and there are many such subsets. Hence, we will need to have a large number of intermediate classes to implement the common functionality between different subsets. This makes it hard/inefficient to implement through intermediate classes, as we require large number of these intermediate classes.
I believe 2 is also not the best solution, because it requires code replication, which will cause the problems of code maintanance.
Edit: I have tried to simplify the question to give a clear picture in response to the comments.
You can define your common implementations within template functions, and call them as desired from each class to implement the interface function.
Using your interface P, classes A, B, and C, it gives the following.
struct P {
virtual int X() = 0;
};
template <typename T>
int CommonAB( T const & t ) { return t.x; }
template <typename T>
int CommonBC( T const & t ) { return t.y; }
template <typename T>
int CommonCA( T const & t ) { return t.x+t.y; }
struct A : public P {
int X() { return CommonAB( *this )+CommonCA( *this ); }
protected:
int x;
int y;
friend int CommonAB<A>( A const & );
friend int CommonCA<A>( A const & );
};
struct B : public P {
int X() { return CommonBC( *this )+CommonAB( *this ); }
protected:
short x;
short y;
friend int CommonBC<B>( B const & );
friend int CommonAB<B>( B const & );
};
struct C : public P {
int X() { return CommonCA( *this )+CommonBC( *this ); }
protected:
char x;
char y;
friend int CommonCA<C>( C const & );
friend int CommonBC<C>( C const & );
};
int main()
{
A a;
B b;
C c;
a.X();
b.X();
c.X();
return 0;
}
Within a class, I am trying to sort a vector, by passing a method of the same class. But it gives errors at the time of compilation. Can anyone tell what the problem is? Thank you!
it gives the following error:
argument of type bool (Sorter::)(D&, D&)' does not matchbool (Sorter::*)(D&, D&)'
I have also tried using sortBynumber(D const& d1, D const& d2)
#include<vector>
#include<stdio.h>
#include<iostream>
#include<algorithm>
class D {
public:
int getNumber();
D(int val);
~D(){};
private:
int num;
};
D::D(int val){
num = val;
};
int D::getNumber(){
return num;
};
class Sorter {
public:
void doSorting();
bool sortByNumber(D& d1, D& d2);
std::vector<D> vec_D;
Sorter();
~Sorter(){};
private:
int num;
};
Sorter::Sorter(){
int i;
for ( i = 0; i < 10; i++){
vec_D.push_back(D(i));
}
};
bool Sorter::sortByNumber(D& d1, D& d2){
return d1.getNumber() < d2.getNumber();
};
void Sorter::doSorting(){
std::sort(vec_D.begin(), vec_D.end(), this->sortByNumber);
};
int main(){
Sorter s;
s.doSorting();
std::cout << "\nPress RETURN to continue...";
std::cin.get();
return 0;
}
Make Sorter::sortByNumber static. Since it doesn't reference any object members, you won't need to change anything else.
class Sorter {
public:
static bool sortByNumber(const D& d1, const D& d2);
...
};
// Note out-of-class definition does not repeat static
bool Sorter::sortByNumber(const D& d1, const D& d2)
{
...
}
You should also use const references as sortByNumber should not be modifying the objects.
Unless you have a really good reason to do otherwise, just define operator< for the type of items you're sorting, and be done with it:
class D {
int val;
public:
D(int init) : val(init) {}
bool operator<(D const &other) { return val < other.val; }
};
class sorter {
std::vector<D> vec_D;
public:
void doSorting() { std::sort(vec_d.begin(), vec_D.end()); }
};
The way you're writing your sorter class depends on knowing a lot about the internals of the D class, to the point that they're practically a single class (e.g., it looks like neither can do much of anything without the other).
At a guess, your sorter may be a somewhat stripped-down version of your real code. The SortByNumber makes it sound like the original code might support a number of different kinds of keys, something like:
class D {
std::string name;
int height;
int weight;
// ...
};
and you'd want to be able to sort D objects by name, height, or weight. In a case like that, the comparisons are really still related to the D class, so I'd probably put them into a common namespace:
namespace D {
class D {
std::string name;
int height;
int weight;
public:
friend class byWeight;
friend class byHeight;
friend class byName;
// ...
};
struct byWeight {
bool operator()(D const &a, D const &b) {
return a.weight < b.weight;
}
};
struct byHeight {
bool operator()(D const &a, D const &b) {
return a.height < b.height;
}
};
struct byName {
bool operator()(D const &a, D const &b) {
return a.name < b.name;
}
};
}
Then sorting would look something like:
std::vector<D::D> vec_D;
// sort by height:
std::sort(vec_D.begin(), vec_D.end(), D::byHeight());
// sort by weight:
std::sort(vec_D.begin(), vec_D.end(), D::byWeight());
// sort by name:
std::sort(vec_D.begin(), vec_D.end(), D::byName());
Note that this does not use free functions. For this kind of purpose, a functor is generally preferable. I've also used a namespace to show the association between the object being sorted and the different ways of sorting it. You could make them nested classes instead, but I'd generally prefer the common namespace (keep coupling as loose as reasonable).
In any case, I would not give access to the raw data (even read-only access) via the object's public interface if it could be avoided (and in this case, it can be).
I see no reason for sortByNumber() to be a member function. When it's a member function it gains access to things it doesn't need (and therefore shouldn't have access to). Either extract the method and refactor it into a function object:
struct sortByNumber {
bool operator()(const D& d1, const D& d2) const {
return d1.getNumber() < d2.getNumber();
}
};
or make it a free function. Given the choice you should prefer a function object, because that makes it possible for the compiler to inline the code if it so chooses. Then, you can sort like so:
std::sort(vec_D.begin(), vec_D.end(), sortByNumber());
That said, you can get the code to compile as is like so, with boost::bind():
std::sort(vec_D.begin(), vec_D.end(),
boost::bind(&Sorter::sortByNumber, this, _1, _2));
You will need the boost libraries for that to work, and you will need to #include <boost/bind.hpp>.
I don't see any reason to make sortByNumber as a member function of class Sorter. You can do the sorting much more easily avoiding all the ugly bind code if you make it a free function. Also, you should use const wherever it is applicable in the code. Following is the example of doing it using free function:
First change the int getNumber() to const function as int getNumber() const;
Then write your free function sortByNumber again taking parameters by const reference.
bool sortByNumber(const D& d1, const D& d2);
You can call sort as :
std::sort(vec_D.begin(), vec_D.end(), sortByNumber);