All the standard says about inheritance from base classes is that it is allowed:
17.6.5.11 Derived classes [derivation]
1 - An implementation may derive any class in the C++ standard library from a class with a name reserved to the implementation.
It doesn't say either way whether methods (and, indeed, other members such as typedefs) are allowed to be inherited from a base class; obviously, since implementations do so, the standard should describe this behaviour.
In any case, detecting e.g. reserve
by cast to a member function type is not guaranteed to work even if a member of the most derived type, since:
17.6.5.5 Member functions [member.functions]
2 - An implementation may declare additional non-virtual member function signatures within a class:
- by adding arguments with default values to a member function signature186; [...]
186) Hence, the address of a member function of a class in the C++ standard library has an unspecified type.
The correct way to check whether reserve
exists is to attempt to call it:
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
{};
This has the advantage of paralleling the container requirements (table 103 for unordered_set
), which are normative where the synopses tend more to the informative.