Is there a more efficient way to structure / template C ++ than this?

The basic idea is that I have a "family" of classes that do the same thing, but in a slightly different way. This "family" is used in a "high-performance" loop, so speed matters. In addition, a specific family is defined by the configuration file ...

The problem is that there is a huge repetition of code in the main function. Is there a better way to structure this, so I don’t need to write HP<objx> test and test.loop(bobloblaw) three times? (In practice, this piece of code has a lot more lines than 2 ...)

 class obj1 { public: double f(double x) const { return 1.; } }; class obj2 { public: double f(double x) const { return x; } }; class obj3 { public: double f(double x) const { return x*x; } }; template <class O> class HP { private: O obj; public: double loop(const vector<double>& x) { double s = 0.; for (auto i : x) s += obj.f(i); return s; } }; int main() { string config = "bob"; double result = 0; vector<double> bobloblaw; /* Read configuration file to determine which object to use. */ if (config == "obj1") { HP<obj1> test; result = test.loop(bobloblaw); } else if (config == "obj2") { HP<obj2> test; result = test.loop(bobloblaw); } else if (config == "obj3") { HP<obj3> test; result = test.loop(bobloblaw); } return result; } 
+4
source share
2 answers

The following has not been verified, but should work:

 class obj1 { public: double f(double x) const { return 1.; } }; class obj2 { public: double f(double x) const { return x; } }; class obj3 { public: double f(double x) const { return x*x; } }; class HPbase { public: virtual double loop(const vector<double>&) = 0; }; template <class O> class HP: public HPbase { public: double loop(const vector<double>& x) { double s = 0.; for (auto i : x) s += obj.f(i); return s; } private: O obj; }; std::unordered_map<std::string, std::unique_ptr<HPbase>> decode{ {"obj1"}, new HP<obj1>()}, {"obj2"}, new HP<obj2>()}, {"obj3"}, new HP<obj3>()} }; int main() { string config = "bob"; double result = 0; vector<double> bobloblaw; /* Read configuration file to determine which object to use. */ result = decode[config].loop(bobloblaw); } 

Please note that the only addition is the base class for HP<> and a card that replaces the if / else logic of your code.

+4
source

Could you please have these 3 classes be subclasses with the same parent? main still needs to be assigned for testing using the right subclass, but the test itself will be declared a common superclass.

The disadvantage here is that there may be a (possibly slight) performance hit, since the compiler would not know when creating the code for test.loop which version will be used, and therefore it will have to decide at runtime.

An alternative that would get around this would be to write a generic code in the form of a macro, which would thus only be written once, but expanded into 3 separate copies, each of which the compiler could optimize based on the variant of the test to be used. It can make debugging a bitch, but if your focus is on performance and reduces source redundancy (and not so much for the object), this can be a good compromise.

+3
source

Source: https://habr.com/ru/post/1390948/


All Articles