Template instantiation does not "inherit"

The title is quoted from this SO. He discusses the use of SFINAE to detect the existence of a member function with a given signature, and points out a method failure in the accepted answer when dealing with inherited member functions. Specifically, this explanation is as follows

If you're not already smart about this, then a look at the definition std::shared_ptr<T>

in the title will shed some light. This implementation std::shared_ptr<T>

derives from the base class from which it inherits operator*() const

. Thus, an instance of a template SFINAE<U, &U::operator*>

that is a "lookup" operator for U = std::shared_ptr<T>

will not be executed because it std::shared_ptr<T>

does not have it operator*()

in its own right, and the template creation does not "inherit".

This binding does not affect the famous SFINAE approach, using the "Theofofof () Trick" to only detect if T has some mf member function (see, for example, this answer and comments).

Using the terminology from the answer, what is the difference between using T::mf

as a template argument to instantiate a type vs when the compiler determines it by inferring a template function argument? What does "template instance do not inherit" mean? And finally, why doesn't this affect the simplicity of checking the existence of a member, for example here ?

+3


source to share


1 answer


Minimized example:

struct A {
    void a() const;
};

struct B : A {};

template<typename U, void (U::*)() const> struct SFINAE {};
template<typename U> void Test(SFINAE<U, &U::a>*) { }

int main(void)
{
    Test<B>(0); // doesn't compile
    return 0;
}

      

Demo .



The problem is that when B::a

inherited from A

, the type &B::a

is actually a "pointer to member A

" - and although it is usually a pointer to a base element can be implicitly converted to pointer-to-member-derived, this conversion does not apply to template arguments without a type, according to §14.3.2 [temp.arg.nontype] / p5:

The following conversions are performed for each expression used as a non-type template-argument. If a template argument of a non-type type cannot be converted to the type of the corresponding template parameter, then the program is poorly formed.

  • [...]
  • For a non-type template-parameter of a type pointer to a member function, if the template-argument has a type std::nullptr_t

    , the null member pointer conversion (4.11) is applied; otherwise, there is no conversion. If the template argument is a set of overloaded member functions, the member function from the set (13.4) is selected.
+3


source







All Articles