Call the "base" template function from a C ++ template specialization that "overrides" it?

Question:

Is there a way to call the "base" template function from a specialized template function in C ++, how can a child class access the parent versions of virtual methods when overriding them? (NOTE: I suspect the answer is no, but would like to be wrong)

Context:

I often find myself a specialist in template functions only because a special case needs additional preliminary or subsequent processing, and not because the "guts" of the code have changed.

To give a far-fetched example:

With inheritance, you can do the following:

struct base { virtual void go() { printf("%p", this); } }; struct foo : base { virtual void go() { printf("this foo lives at "); base::go(); } }; 

... and calling foo :: go () will print "this foo lives in <address>"

With templates:

 template <typename T> void go(T const &t) { printf("%p\n", &t); } template <> void go(foo const &f) { printf("this foo lives at "); ??? how to access "base" template ??? } 

You can get around the problem in an ugly way by decomposing the mess of small helper functions and specializing in them, rather than the function that you really need:

 template <typename T> void _go_pre(T const &t) { /* do nothing */ } template <typename T> void _go_post(T const &t) { /* do nothing */ } template <typename T> void go(T const &t) { _go_pre(t); /* just in case */ printf("%p\n", &t); _go_post(t); } template<> void _go_pre(foo const &t) { printf("this foo lives at "); } 

... but this significantly clogs the code, because now the base template needs to foresee all the ways that its "child" specialization can redefine, and most types will use several, if any, of these hooks. The mess becomes unreadable and unnoticeable quite quickly because the cause of these hooks is unknown at the place where they are identified, and you need to check the various combinations of hooks used / not used.

All this is exactly the same as the problems you would have with redefining virtual methods in a world where the child class could not access the original version provided by the parent class.

+4
source share
2 answers

This is not possible directly. However, you can make fewer (and IMO less ugly) helpers, such as:

 template <typename T> void base_go(T const &t) { printf("%p\n", &t); } template <typename T> void go(T const &t) { base_go(t); } template<> void go(foo const &t) { printf("this foo lives at "); base_go(t); } 

Alternatively, you can put the base_ variants in a separate namespace instead of giving them changed names.

+2
source

If your foo is a regular type, you can simply create a function (without a template) and reload the internal version of the template:

 #include <iostream> struct A {}; template<class T> void f(T const&) { std::cout << "in f<T>(T const&)" << std::endl; } void f(A const& a) { std::cout << "in f(A const&)" << std::endl; f<A>(a); } int main() { A a; f(a); return 0; } 
0
source

Source: https://habr.com/ru/post/1484209/


All Articles