The following code successfully compiled with clang and MSVC but fail to compile in GCC 6.1.0.
#include
template
The standard's specification for types and their members is normative text, unless it explicitly says otherwise. As such, an implementation is required to follow that... to the extent that an implementation is required to follow anything from the standard.
And that extent is the "as if" rule. Namely, the implementation is allowed to do what it wants so long as the type behaves "as if" it were done as specified. The reason the standard has specific language stating that types can be derived from arbitrary, implementation-provided base classes is because that is something which a user can detect. It's visible behavior (through implicit conversions and the like) and therefore the standard would have to make an exception in order to allow for it.
Inheriting a member is almost the same thing as declaring it in your main class. Indeed, the only way I know of to tell the difference is to do what you did here: use template argument deduction rules. Even though you can specify the member as Derived::get
, if it really comes from some base class, the compiler will know.
However, [member.functions] comes to GCC's rescue here. It has explicit language allowing standard library implementations to add additional overloads to a class. Because of that, your use of std::shared_ptr
here is not well-defined behavior. Indeed, footnote 187 clarifies this:
Hence, the address of a member function of a class in the C++ standard library has an unspecified type.
That's merely a footnote, but the intent seems clear: you cannot rely on any particular implementation to return any particular type of member pointer. Even if you applied a cast operation to the right signature, there is no guarantee that it would work.
So while the class definition in the standard library is normative text, [member.functions] makes it clear that the only thing you can guarantee about those definitions is that you can call those functions using the arguments provided. Anything else, like getting member pointers, is implementation-defined.