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;
}
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.
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);
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);
I'm using two 3rd party libraries, which both implement their own 2D vector class. Unfortunately, I have to work with both of them, so is there anyway I can write some "friend" functions so that one can automatically be converted to the other when I try to use them in functions from the other library?
Auto-cast seems not to be possible. You could define global conversion function and call it explicitly. Could you post definition of that classes? May be some trick with inheritance will be possible.
Something like this, but it is not auto-cast:
class T1 {};
class T2 {};
class UnionType : public T1, public T2
{
public:
UnionType( const T1& val ) {} // real storing should be here
UnionType( const T2& val ) {} // real storing should be here
operator T1() { T1 t; return t; } // real conversion should be here
operator T2() { T2 t; return t; } // real conversion should be here
};
int main()
{
T1 t;
T2 t2 = UnionType(t);
return 0;
}
Conversion operators have to be member functions.
In situations like this, I have used a convert<X,Y> function template, with full specialisations or overloads for each pair of types that I want to "cast". In this case, you wouldn't need the template, just two overloads, one in each direction, because for a given X there's only ever one thing you convert it to.
Then it's rarely any trouble to switch between one and the other (the notable exception being when you're using template code which requires that one parameter type be convertible to another). You can easily see in the code the boundary between the two APIs, without introducing much noise.
The reason I've had this situation a lot is writing OS abstraction layers - the underlying OS has one set of objects or opaque handles for various OS concepts, and the API you're implementing has another. It's much nicer to just "convert" from one set of concepts to the other, without having ConvertHostMutexToGuestMutex, ConvertGuestMutexToHostMutex, ConvertHostSocketOptsToGuestSocketOpts etc. The disadvantage is the usual one with widespread overloading, that it's not necessarily obvious where the functions are actually defined.
One way would be to derive from those classes and provide conversion operators for one another. But then you have to use the derived class objects through out your code. Here is some sample code:
class ThirdParty1
{
public:
ThirdParty1(int x, int y) : m_x(x), m_y(y)
{
}
int getX() const { return m_x; }
int getY() const { return m_y; }
private:
int m_x;
int m_y;
};
class ThirdParty2
{
public:
ThirdParty2(int x, int y) : m_x(x), m_y(y)
{
}
int getX() const { return m_x; }
int getY() const { return m_y; }
private:
int m_x;
int m_y;
};
template<class Type, class AdaptedType>
class TP1Adaptor : public Type
{
public:
TP1Adaptor(int x, int y): Type(x,y)
{
}
operator AdaptedType()
{
return AdaptedType(getX(),getY());
}
};
typedef TP1Adaptor<ThirdParty1, ThirdParty2> First2D;
typedef TP1Adaptor<ThirdParty2, ThirdParty1> Second2D;
void f(ThirdParty1 tp)
{
}
void f1(ThirdParty2 tp)
{
}
int main()
{
First2D f(0,0);
f1(f);
return 0;
}