模板参数,#define和代码重复问题

7

我有很多像这样的代码:

#define WITH_FEATURE_X

struct A {
#ifdef WITH_FEATURE_X
  // ... declare some variables Y
#endif
  void f ();
};

void A::f () {
  // ... do something
#ifdef WITH_FEATURE_X
  // ... do something and use Y
#else
  // ... do something else
#endif
  // ... do something
}

我希望用模板参数替换#defines:

template < int WITH_FEATURE_X > // can be 0 or 1
struct A;

但我不想为A<0>::f()和A<1>::f()几乎重复整个A::f()的代码,仅仅因为这些代码与参数有关。我也不想在之前的#ifdef中调用函数。有什么通用的解决方案吗?

4个回答

2

如果你想避免重复函数 f 的逻辑,可以使用模板方法模式(不是那种template)。

template <bool enabled>
class helper {
protected:
    void foo() { /* do nothing */ }
};

template <>
class helper<true> {
protected:
    Y y;
    void foo() { /* do something with y */ }
};

struct A : private helper<WITH_FEATURE_X> {
    void f() {
        // common stuff

        foo(); // optimized away when WITH_FEATURE_X is false

        // more common stuff
    }
};

这似乎是与Benoît的建议相同,但知道模式的名称并了解如何将其应用于函数是很好的。谢谢。 - Thomas

1

我相信您想要的是与 D 语言中存在的 "static if" 命令等效的命令。很遗憾,在 C++ 中不存在这样的功能。

请注意,如果您的代码的某些部分取决于您请求的功能,则这些部分不属于主函数,因为它们不是裸算法的一部分。因此,将这样的功能委派给函数似乎是一个不错的选择。

编辑
如果您的 #ifdef 语句用于以不同方式执行相同的子任务,则定义子函数是正确的做法。这将使您的代码更具可读性,而不是降低可读性。

如果它们用于完全不同的操作,那么您的代码已经凌乱了。为此,做点什么。

至于您担心出现的性能问题,请相信您的编译器。

编辑2
我忘记提及您的代码的第一部分的答案:使用以下技巧根据 "feature" 添加或删除成员。

namespace helper
{
  template<int feature>
  struct A;

  template<>
  struct A<0> { // add member variables for case 0 };

  template<>
  struct A<1> { // add member variables for case 1 };
}

template<int feature>
class A : private helper::A<feature>
{
  // ... functions here
};

是的,似乎需要类似于“静态if”的东西。也许在这种情况下可以使用boost模板(如enable_if)实现? 我担心函数会使代码变得非常混乱,会有嵌套调用,并且代码会变得相当人为,难以阅读,可能速度优化也不够好。 - Thomas
那是一个不错的想法,使用helper::A! 我将尝试稍后用函数和你的技巧重新编码一些#ifdefs,并查看是否喜欢结果。 - Thomas

0

常见的解决方案就是使用 #ifdef。:-)


0

我不明白常见代码复制的意义。如果您使用模板参数,则只需用if(WITH_FEATURE_X)替换#ifdef。 您是在讨论编译器产生的代码膨胀吗? 由于您正在尝试替换#ifdef,我假设您在任何时候都将使用A<0>或A<1>。所以即使是编译器,我也不认为会有代码膨胀。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接