Производительность C ++: шаблон против boost.any

Мне было интересно, если использование классов boost.any (без RTTI) везде, где могут использоваться шаблоны, замедлит работу программы. Поскольку boost any на самом деле является оберткой вокруг шаблонного класса, можно сказать, что с современными оптимизациями компилятора это даст тот же эффект, я прав?

tpl_vs_any.hpp

#include <iostream>
#include <vector>

using namespace std;

template<class T> class tpl
{
T content;
public:
tpl(const T& value) : content(value) {}
operator T() const
{
return content;
}
};

class any
{
public:

any() : content(0) {}

any(const any& other) : content(other.content -> clone()) {}

template<class T> any(const T& value) : content(new holder<T>(value))
{
}

~any()
{
delete content;
}

class placeholder
{
public:
placeholder() {}
virtual placeholder* clone() const = 0;
};

template<class T> class holder : public placeholder
{
public:
T content;

holder(const T& value) : content(value) {}
~holder() {}

placeholder* clone() const
{
return new holder<T>(content);
}
};

template<class T> operator T () const
{
return dynamic_cast<holder<T>*>(content)->content;
}

placeholder* content;
};

template<class T> void test()
{
for (int i = 0; i < 10000; ++i)
{
vector<T> a;
a.push_back(23.23);
a.push_back(3.14);

double x = (double)a[0];
}
}

Поэтому было бы правильно сказать, что:

test<any>();

Это так же быстро, как:

test<tpl<double>>();

Предполагая, что вы знаете, так же, как компилятор делает во втором примере, что boost::any используется только как двойной в этой ситуации? (Нет RTTI для любого класса).

Меня больше интересуют аргументы за и против этого тезиса.

Кроме того, существуют ли конкретные ситуации, в которых есть разница между этими методами?

Редактировать:
Тест производительности 2:

  • Пример 1: 1966,57 мс
  • Пример 2: 1320,37 мс

Кажется, что разница относительно велика.

Изменить 2:
Поскольку было несправедливо сравнивать первичный тип данных double против класса any Я сделал новый тест:

#include "tpl_vs_any.hpp"
int main()
{
test<any>();
return 0;
}

Скорость: 1794,54 мс

#include "tpl_vs_any.hpp"
int main()
{
test<tpl<double>>();
return 0;
}

Скорость: 1715,57 мс

Протестировал его несколько раз, практически одинаковые тесты.

5

Решение

Поэтому было бы правильно сказать, что:

Это так же быстро, как:

Предполагая, что вы знаете, как это делает компилятор во втором примере, что boost :: any используется только как double в этой ситуации?

Нет. Текущие компиляторы не достигают такого уровня самоанализа. boost::any будет медленнее.

Конечно, вы можете просто запустить код и убедиться в этом сами.

2

Другие решения

boost::any внутренне содержит указатель на объект, который он выделяет new, Одна из вещей, которая делает std::vector значительно быстрее, чем, скажем, std::list заключается в том, что вектор хранит все свои объекты в непрерывном хранилище в одном выделении, что, помимо очевидного сокращения накладных расходов на выделение памяти, также намного более дружественно к кешу.

Также есть детали добавления RTTI к распределению, что, как правило, тривиально, но в случае действительно небольших типов, таких как double значительно увеличивает накладные расходы на хранение.

boost::any не является частью стандарта; это конкретная реализация определенного шаблона. Так что вы могли бы просто сравнить его; нет других конкурирующих «стандартных реализаций».

2