我想创建一个基于预处理器定义的类的 stub 或模拟版本。当预处理器宏设置为“启用”时,该类只是一个普通类。当设置为“禁用”时,该类是一个空 stub ,编译器有望完全优化它。然而,与真实类一起编译或未完全编译的代码也应该与 stub 类具有相应的行为。
这是一个可能看起来像的例子:
class _foo {
public:
foo(int x) : x_(x) {}
void add(int x) { x_ += x; }
void add(const char *str) { x_ += atoi(str); }
bool isset(void) { return x_ > 0; }
private:
int x_;
};
#if ENABLE_FOO
using foo = _foo;
#else
class foo {
public:
foo(int x) {}
void add(int x) { return; }
void add(const char *str) { return; }
bool isset(void) { return false; }
};
#endif
isset()
的定义旨在允许像 if (a_foo.isset()) { code(); }
这样的代码被优化到一无所有。显然,这不能普遍适用于任何方法和该方法的任何使用。需要设计类,以便 0、false、NULL 等在禁用情况下是合理的返回值。
这工作正常,但必须保留 foo
的 stub 版本与真实版本完美同步。对任何方法的每次更改都必须在 stub 中复制。这很烦人。如何使 stub 更加自动化?理想情况下可以写 class foo_stub : public stub<foo> {};
或 STUB(foo)
stub 类是单独创建的。
为此,到目前为止,我已经能够想出这个:
class foo {
public:
CTOR_STUB(_foo, foo);
METHOD_STUB(_foo, add);
METHOD_STUB(_foo, isset);
};
这会创建 _foo
的 stub 版本.确实需要列出每个方法名称,但不需要提供返回类型、参数和参数数量。所有重载(即两种 add()
方法)都包含在一个 METHOD_STUB
中。 .重载可以有不同的返回类型。如果 stub 方法是方法模板,它甚至可以工作。
下面是执行此操作的宏:
#define METHOD_STUB(base, func) \
template <typename... Args> \
auto func(Args... args) { \
using RetType = decltype(std::declval<base>().func(std::forward<Args>(args)...)); \
return (RetType)0; }
#define CTOR_STUB(base, name) \
template <typename... Args> \
name(Args... args) { return; base _dummy{std::forward<Args>(args)...}; }
想法是定义一个模板,该模板要求 stub 类中存在具有适当参数和返回类型的方法才能正确编译,但编译器将优化为无。
有没有办法避免宏,并且只使用模板来做到这一点?似乎有人希望方法的名称成为模板参数,但我不知道该怎么做。
有没有办法避免在 CTOR_STUB()
中提供当前类的名称? ?编译器确实知道名称,但我看不出有什么方法可以将名称作为可用于定义构造函数模板的符号,而不是将类名称作为文本字符串或类型。
是否有一些缺陷会允许 stub 正确编译或在类的真实版本不会执行相同操作时无法编译?
最佳答案
不是一个完美的解决方案,但你可以做到
#ifdef ENABLE
#define IF_ENABLED(x) x
#define IF_DISABLED(x)
#else
#define IF_ENABLED(x)
#define IF_DISABLED(x) x
#endif
class Foo {
public:
foo(int x) IF_ENABLED(: x_(x)) {}
void add(int x) { IF_ENABLED(x_ += x;) }
void add(const char *str) { IF_ENABLED(x_ += atoi(str);) }
bool isset(void) { IF_ENABLED(return x_ > 0;) IF_DISABLED(return false;) }
private:
#ifdef ENABLE
int x_;
#endif
};
关于c++ - 创建 C++ 类的 stub 版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43772929/