问题:
有没有办法从C++中的专用模板函数调用"基本"模板函数,子类在覆盖它们时可以访问父类虚拟方法的方式?(注意:我怀疑答案是"不"但是会喜欢错误)
上下文:
我经常发现自己专门设计模板功能只是因为特殊情况需要额外的预处理或后处理,而不是因为代码的"胆量"已经改变.
举一个人为的例子:
通过继承,您可以执行以下操作:
struct base {
virtual void go() { printf("%p", this); }
};
struct foo : base {
virtual void go() { printf("this foo lives at "); base::go(); }
};
Run Code Online (Sandbox Code Playgroud)
...并且调用foo :: go()将打印"this foo生活在<address>"
但是,使用模板:
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 ???
}
Run Code Online (Sandbox Code Playgroud)
你可以通过分解一堆小辅助函数并专门化它们而不是你真正关心的函数来以一种丑陋的方式解决这个问题:
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 "); }
Run Code Online (Sandbox Code Playgroud)
...但是这会使代码显着混乱,因为现在"基础"模板需要预测"子"专业化可能覆盖它的所有方式,并且大多数类型将使用这些钩子中的少数(如果有的话).混乱变得难以理解并且很快就无法维护,因为这些钩子的原因在定义时并不为人所知,并且您必须测试已使用/未使用的钩子的不同组合.
所有这些与您在子类无法访问父类提供的原始版本的世界中使用虚拟方法覆盖时遇到的问题完全相同.
直接是不可能的。但是,您可以使用更少的(并且在我看来不那么难看的)助手,如下所示:
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); }
Run Code Online (Sandbox Code Playgroud)
作为替代方案,您可以将base_变体放入单独的命名空间中,而不是给它们提供修改后的名称。