Ответ 1
Весь стандарт говорит о наследовании от базовых классов, что разрешено:
17.6.5.11 Производные классы [вывод]
1 - реализация может выводить любой класс в стандартной библиотеке С++ из класса с именем, зарезервированным для реализации.
В обоих случаях не указано, разрешены ли методы (и, действительно, другие члены, такие как typedefs), наследуемые от базового класса; очевидно, так как реализации делают это, стандарт должен описывать это поведение.
В любом случае, обнаружение, например, reserve
путем приведения в тип функции-члена не гарантируется работа, даже если член самого производного типа, поскольку:
17.6.5.5 Функции-члены [member.functions]
2 - реализация может объявить дополнительные не виртуальные сигнатуры функций-членов внутри класса:
- путем добавления аргументов со значениями по умолчанию в подпись функции-члена 186; [...]
186) Следовательно, адрес функции-члена класса в стандартной библиотеке С++ имеет неопределенный тип.
Правильный способ проверить, существует ли reserve
, попытаться вызвать его:
template< typename C, typename = void >
struct has_reserve
: std::false_type
{};
template< typename C >
struct has_reserve< C, typename std::enable_if<
std::is_same<
decltype( std::declval<C>().reserve( std::declval<typename C::size_type>() ) ),
void
>::value
>::type >
: std::true_type
{};
Это имеет преимущество параллельного требования к контейнеру (таблица 103 для unordered_set
), которые являются нормативными, когда синонимы больше ориентируются на информативность.