可扩展的 SFINAE 条件覆盖
scalable SFINAE conditional override
上下文
我的情况类似于这里描述的情况:条件(SFINAE)覆盖。
除了这个问题,只有一个函数被有条件地覆盖。我想知道如何获得一个解决方案,可以为 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。好的,所以我尝试不使用覆盖关键字并获得与 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()
两个编译器都未能在运行时完成任务,这让我相信我在我的示例中做错了什么,或者我试图打破一个规则。请开导我。
目标
目标是拥有可以覆盖基类中虚拟方法的任何组合的东西,而无需为每个组合创建"版本"。注意:这应该在编译时完成。
问题是模板函数不能是virtual
函数。
我想到的最佳选择是创建一个具有专用化的oFoo
模板结构,以根据布尔模板值覆盖(或不覆盖)foo()
template <bool>
struct oFoo : virtual public A
{ void foo () override { std::cout << "B::foo()" << std::endl; } };
template <>
struct oFoo<false>
{ };
然后是相同的oBar
模板结构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
传承,避免钻石问题。
以下是完整的编译示例
#include <iostream>
#include <type_traits>
struct A
{
virtual void foo() { std::cout << "A::foo()" << std::endl; }
virtual void bar() { std::cout << "A::bar()" << std::endl; }
void print() { foo(); bar(); }
};
template <bool>
struct oFoo : virtual public A
{ void foo () override { std::cout << "B::foo()" << std::endl; } };
template <>
struct oFoo<false>
{ };
template <bool>
struct oBar : virtual public A
{ void bar () override { std::cout << "B::bar()" << std::endl; } };
template <>
struct oBar<false>
{ };
template <bool FOO, bool BAR>
struct B : virtual public A, public oFoo<FOO>, public oBar<BAR>
{ };
int main ()
{
A *a = new B<true, false>();
a->print();
}
相关文章:
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- 在没有太多条件句的情况下,我如何避免被零除
- 基于多个条件处理地图中的所有元素
- 条件constexpr函数
- 无论条件是否为true,if总是在c++中执行
- 为什么使用SFINAE而不是函数重载
- 使用ios:ate写入到流会覆盖现有文件
- 我可以使用条件运算符初始化C风格的字符串文字吗
- 基于模板值的条件变量
- 如何使用 SFINAE 在方法调用中有条件地定义变量?
- 使用 SFINAE 有条件地解析分配器成员
- 将 SFINAE 条件移到最左侧以提高可读性
- 循环中的IF-ELSE条件:未来的迭代覆盖以前的迭代结果
- 标准::有条件的与SFINAE
- 可扩展的 SFINAE 条件覆盖
- "What happened to my SFINAE" redux:条件模板类成员?
- SFINAE条件和构造函数参数类型
- c++ std条件变量覆盖了很多共享变量
- 条件(SFINAE)覆盖
- 有没有一种通用的方法可以用SFINAE否定decltype条件