Я узнал разницу между статическим и динамическим полиморфизмом, и с тех пор я много чего на нем читал.
Плюс, поскольку я обнаружил, что реализую статический полиморфный интерфейс (таким образом, что класс может использовать объект с определением базового класса, не зная, с каким «производным» классом был создан объект).
Поэтому я провел небольшой тест, чтобы сравнить эти разные реализации.
Вот код:
#include <functional>
#include <iostream>
#include <ctime>
#include <chrono>
#include <memory>
class BaseLambda
{
public:
double run(double param){return m_func(param);};
protected:
BaseLambda(std::function<double(double)> func) : m_func(func) { };
std::function<double(double)> m_func;
};
class DerivedLambda : public BaseLambda
{
public:
DerivedLambda() : BaseLambda([](double param){return DerivedLambda::runImpl(param);}) { };
private:
static double runImpl(double param) {return (param * param) / 2.5;};
};
class BaseVirtual
{
public:
double run(double param){return runImpl(param);};
protected:
virtual double runImpl(double param) = 0;
};
class DerivedVirtual : public BaseVirtual
{
protected:
double runImpl(double param) {return (param * param) / 2.5;};
};template<class C> class BaseTemplate
{
public:
double run(double param){return static_cast<C*>(this)->runImpl(param);};
};
class DerivedTemplate : public BaseTemplate<DerivedTemplate>
{
public:
double runImpl(double param) {return (param * param) / 2.5;};
};int main()
{
std::clock_t c_start = std::clock();
std::unique_ptr<BaseVirtual> baseVirtual = std::make_unique<DerivedVirtual>();
for(unsigned int i = 0 ; i < 1000000 ; ++i) {
auto var = baseVirtual->run(10.6);
}
baseVirtual.reset(nullptr);
std::clock_t c_end = std::clock();
std::cout << "Execution time with virtual : "<< 1000.0 * (c_end-c_start) / CLOCKS_PER_SEC << " ms" << std::endl;c_start = std::clock();
std::unique_ptr<BaseLambda> baseLambda = std::make_unique<DerivedLambda>();
for(unsigned int i = 0 ; i < 1000000 ; ++i) {
auto var = baseLambda->run(10.6);
}
baseLambda.reset(nullptr);
c_end = std::clock();
std::cout << "Execution time with lambda : "<< 1000.0 * (c_end-c_start) / CLOCKS_PER_SEC << " ms" << std::endl;std::unique_ptr<BaseTemplate<DerivedTemplate>> baseTemplate = std::make_unique<DerivedTemplate>();
for(unsigned int i = 0 ; i < 1000000 ; ++i) {
auto var = baseTemplate->run(10.6);
}
baseTemplate.reset(nullptr);
c_end = std::clock();
std::cout << "Execution time with template : "<< 1000.0 * (c_end-c_start) / CLOCKS_PER_SEC << " ms" << std::endl;
}
Дело в том, что когда я запускал это, виртуальная реализация была самой быстрой, в то время как статический полиморфизм должен был быть быстрее.
Вот пример результата выполнения:
Время выполнения с виртуальным: 53 мс
Время исполнения с лямбдой: 94 мс
Время исполнения по шаблону: 162 мс
Я предполагаю, что это из-за некоторой оптимизации компилятора. Я компилирую с GCC 6.3.0.
Мой вопрос: почему реализация шаблона самая медленная? Это действительно из-за оптимизации компилятора, и если да, то каковы они и как я могу изменить свой тест, чтобы иметь «реальное» время выполнения? И если нет, что я сделал не так?
Задача ещё не решена.
Других решений пока нет …