我的情况类似于此处描述的情况:conditional (SFINAE) override。
除了该问题外,只有一个功能有条件地被覆盖。我想知道如何找到一个可以为n个独立函数启用此功能的解决方案。对于链接的问题中描述的答案,这将导致该类的n ^ 2个版本(真/假组合)。
#include <cstdio>
#include <type_traits>
struct A {
virtual void foo() { printf("A::foo()\n"); }
virtual void bar() { printf("A::bar()\n"); }
void print() { foo(); bar(); }
};
template <bool FOO, bool BAR>
struct B : public A {
template <bool b = FOO>
typename std::enable_if<b, void>::type
foo() override { printf("B::foo()\n"); }
template <bool b = BAR>
typename std::enable_if<b, void>::type
bar() override { printf("B::bar()\n"); }
};
int main() {
A *a = new B<true, false>();
a->print();
return 0;
}
但是,g ++-8.1.0似乎没有为重写的方法生成符号并调用A::{foo,bar}()
:
$ g++ -std=c++11 test.cc && ./a.out && nm -C a.out | grep -e foo -e bar
A::foo()
A::bar()
00000000004006de W A::bar()
00000000004006c4 W A::foo()
clang ++-6.0抱怨:
error: only virtual member functions can be marked 'override'
他们修复了一个非常类似的错误:https://bugs.llvm.org/show_bug.cgi?id=13499。好的,所以我尝试不使用override关键字,并得到与g ++相同的结果:
$ clang++ -std=c++11 test.cc && ./a.out && nm -C a.out | grep -e foo -e bar
A::foo()
A::bar()
0000000000400850 W A::bar()
0000000000400820 W A::foo()
两个编译器都无法在运行时完成任务,这使我相信我的示例做错了什么,或者我试图打破一条规则。请赐教。
目标是拥有一些可以覆盖基类中虚拟方法的任意组合的东西,而无需为每个组合创建“版本”。注意:这应该在编译时完成。
答案 0 :(得分:2)
问题在于模板函数不能是virtual
。
我想到的最好的替代方法是创建一个oFoo
模板结构,并对其进行专门化,以根据布尔模板值覆盖(或不覆盖)foo()
template <bool>
struct oFoo : virtual public A
{ void foo () override { std::cout << "B::foo()" << std::endl; } };
template <>
struct oFoo<false>
{ };
然后使用oBar
的{{1}}模板结构
bar()
因此您可以简单地编写template <bool>
struct oBar : virtual public A
{ void bar () override { std::cout << "B::bar()" << std::endl; } };
template <>
struct oBar<false>
{ };
如下
B
观察template <bool FOO, bool BAR>
struct B : virtual public A, public oFoo<FOO>, public oBar<BAR>
{ };
继承以避免钻石问题。
以下是完整的编译示例
virtual