Re: on a design question using C++
On Feb 7, 12:18 pm, James Kanze <james.ka...@gmail.com> wrote:
On Feb 7, 10:42 am, "nvinh...@gmail.com" <nvinh...@gmail.com> wrote:
[...]
Since I am calling this code in a tight loop, I think that I
have to fall back to the first approach. But I then lose the
beauty and clarity of template code.
Just the opposite. You need templates, rather than virtual
functions: make Application a template over the Policy class.
That way, the calls to the policy won't be virtual; you can even
inline the functions in the policy for more speed.
I concur. If the policy is determined before the creation of the
application object and does not change during its lifetime, then this
is optimal. It provides the compiler with as much type information as
possible to optimize the code.
On the other hand, this may be too coarse for your needs. If the
policy is not known until after the construction of the application
and/or may need to change during its lifetime, then you need to use
some form of run-time polymorphism. But you do not want run-time
polymorphism in your performance-critical inner loops, so try to
express the whole algorithms (the calculation loops) in terms of
templates parameterized on policies.
For example, using your test loop as the algorithm:
class Application
{
public:
int algorithm (int n)
{
return algo_->invoke (n);
}
template <class SofteningPolicy>
void setSofteningPolicy (const SofteningPolicy& p)
{algo_.reset (new Algorithm <SofteningPolicy> (p));}
private:
class IAlgorithm
{
public:
virtual int invoke (int n) = 0;
};
template <class SofteningPolicy>
class Algorithm :
public IAlgorithm,
private SofteningPolicy
{
public:
Algorithm (const SofteningPolicy& p)
: SofteningPolicy (p) {}
virtual int invoke (int n)
{
for (int i = 0; i < n; i++)
{
double fval2 = SofteningPolicy::evalFunc (0.1);
double fder2 = SofteningPolicy::evalDeri (0.1);
//cout << " fval2: " << fval2 << ", fderi2: " << fder2 <<
"\n";
}
return 0;
}
};
shared_ptr <IAlgorithm> algo_;
};
Regards,
Vidar Hasfjord