Раздувание кода шаблона с unordered_map

Мне интересно, реализована ли unordered_mapс использованием стирания типа, поскольку unordered_mapи unordered_mapмогут использовать один и тот же код (за исключением приведения, которое в машинном коде не выполняется), то есть реализация обоих может быть основана на unordered_mapдля экономии размера кода.

Обновление:Этот метод обычно называют идиомой тонкого шаблона(спасибо комментаторам ниже за указание на это).

Обновление 2:Меня особенно интересует мнение Говарда Хиннанта. Будем надеяться, что он это прочитает.

Итак, я написал этот небольшой тест:

#include 

#if BOOST
# include 
  using boost::unordered_map;
#else
# include 
  using std::unordered_map;
#endif

struct A { A(int x) : x(x) {} int x; };
struct B { B(int x) : x(x) {} int x; };

int main()
{
#if SMALL
    unordered_map ma, mb;
#else
    unordered_map ma;
    unordered_map mb;
#endif

    ma["foo"] = new A(1);
    mb["bar"] = new B(2);

    std::cout << ((A*) ma["foo"])->x << std::endl;
    std::cout << ((B*) mb["bar"])->x << std::endl;

    // yes, it leaks.
}

И определил размер скомпилированного вывода с различными настройками:

#!/bin/sh

for BOOST in 0 1 ; do
    for OPT in 2 3 s ; do
        for SMALL in 0 1 ; do
            clang++ -stdlib=libc++ -O${OPT} -DSMALL=${SMALL} -DBOOST=${BOOST} map_test.cpp -o map_test
            strip map_test
            SIZE=$(echo "scale=1;$(stat -f "%z" map_test)/1024" | bc)
            echo boost=$BOOST opt=$OPT small=$SMALL size=${SIZE}K
        done
    done
done

Получается, что со всеми настройками, которые я пробовал, много внутреннего кода unordered_mapсоздается дважды:

With Clang and libc++:
          |   -O2   |   -O3   |   -Os
-DSMALL=0 |  24.7K  |  23.5K  |  28.2K
-DSMALL=1 |  17.9K  |  17.2K  |  19.8K


With Clang and Boost:
          |   -O2   |   -O3   |   -Os
-DSMALL=0 |  23.9K  |  23.9K  |  32.5K
-DSMALL=1 |  17.4K  |  17.4K  |  22.3K


With GCC and Boost:
          |   -O2   |   -O3   |   -Os
-DSMALL=0 |  21.8K  |  21.8K  |  35.5K
-DSMALL=1 |  16.4K  |  16.4K  |  26.2K

(с компиляторами из Apple Xcode)

Теперь вопрос: есть ли какая-то убедительная техническая причина, по которой разработчики решили пропустить эту простую оптимизацию?

Также: какого черта эффект -Osпрямо противоположен тому, что рекламируется?

Обновление 3:

Как предложил Никол Болас, я повторил измерения с shared_ptrвместо голых указателей (созданных с помощью make_sharedи приведение с помощью static_pointer_cast). Тенденция результатов та же:

With Clang and libc++:
          |   -O2   |   -O3   |   -Os
-DSMALL=0 |  27.9K  |  26.7K  |  30.9K
-DSMALL=1 |  25.0K  |  20.3K  |  26.8K


With Clang and Boost:
          |   -O2   |   -O3   |   -Os
-DSMALL=0 |  35.3K  |  34.3K  |  43.1K
-DSMALL=1 |  27.8K  |  26.8K  |  32.6K

17
задан Community 23 May 2017 в 11:52
поделиться