Правильная подпись / обнаружение присутствия Container :: reserve ()

Учитывая тип C который является контейнером, соответствующим STL, как правильно определить, C содержит функцию-член reserve? Я попробовал следующий подход (с GCC 4.6.3):

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( &C::reserve ),
void (C::*)( typename C::size_type )
>::value
>::type >
: std::true_type
{};

Это работает для C являющийся std::vectorно не для неупорядоченных контейнеров, например std::unordered_set, Причина в том, что reserve является (прямой) функцией-членом std::vector, но для неупорядоченных контейнеров он унаследован от базового класса, то есть его подпись не void (C::*)( typename C::size_type ) но void (B::*)( typename C::size_type ) для некоторого неопределенного базового класса B из C,

Я знаю, как обойти это и обнаружить reserve даже если наследуется, но выглядит неуклюже, и мне интересно, что разрешено стандартом. Так…

Мой вопрос: позволяет ли стандарт reserve быть унаследованным от неопределенного базового класса или это синопсис обязательный и требует прямой функции-члена?

11

Решение

Все, что говорит стандарт о наследовании от базовых классов, это то, что оно разрешено:

17.6.5.11 Производные классы [происхождение]

1 — Реализация может выводить любой класс в стандартной библиотеке C ++ из класса с именем, зарезервированным для реализации.

Так или иначе не сказано, разрешено ли методам (и, действительно, другим членам, таким как typedefs) наследоваться от базового класса; Очевидно, что поскольку реализации делают это, стандарт должен описывать это поведение.

В любом случае, например, обнаружение reserve приведение к типу функции-члена не гарантируется, даже если он является членом самого производного типа, поскольку:

17.6.5.5 Функции-члены [member.functions]

2 — Реализация может объявлять дополнительные не виртуальные сигнатуры функций-членов в классе:

  • путем добавления аргументов со значениями по умолчанию к сигнатуре функции-члена186; […]

186) Следовательно, адрес функции-члена класса в стандартной библиотеке C ++ имеет неопределенный тип.

Правильный способ проверить, 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), которые являются нормативными, когда краткие обзоры имеют тенденцию к информативности.

11

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

Других решений пока нет …

По вопросам рекламы [email protected]