2010-09-01 69 views
7

我有很多这样的代码:模板参数,#define和代码重复

#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 
} 

,我想用模板参数来代替#定义:

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

但我对于A < 0> :: f()和A < 1> :: f(),几乎不需要为几条依赖于参数的行重复几乎整个A :: f()的代码。我也不想调用函数而不是以前的#ifdefs。什么是常用解决方案?

回答

1

我相信你想要的是与D语言中存在的“static if”命令等价的东西。恐怕C++中不存在这样的特性。

请注意,如果代码的某些部分因请求的功能而异,则这些部分不属于主函数,因为它们不属于裸算法的一部分。因此,在功能中委派这些功能的选项看起来很不错。

编辑
如果#ifdef语句是用来做同样的子任务不同,然后定义子功能是做正确的事。它会使你的代码更具可读性,而不是更少。

如果它们用于完全不同的动作,那么您的代码已经混乱了。做点什么吧。

至于你害怕可能出现的性能问题,请相信你的编译器。

EDIT2
我忘记了答案提给你的代码的第一部分:使用下面的技巧添加或删除取决于“功能”的成员。

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 
}; 
+0

是,一些类似“静若”似乎是必要的。也许在这种情况下,可以使用boost模板(比如enable_if)吗? 恐怕函数会让代码变得非常混乱,会有嵌套的调用,代码会变得非常虚假,难以理解,并且可能会因速度而优化得更少。 – Thomas 2010-09-01 06:35:13

+0

这对于helper :: A来说是个不错的主意!我会在后面尝试重新编写一些带有函数和你的技巧的#ifdefs,看看我是否喜欢res ULT。 – Thomas 2010-09-01 07:32:45

0

常见的解决方法,就是使用#ifdef恐怕。 :-)

0

我不明白通用代码的重复。如果你正在使用模板参数,你只需用if(WITH_FEATURE_X)替换你的#ifdef。 你是否在谈论编译器的代码膨胀? 由于您试图替换#ifdef,我假设您在任何时候都会使用A < 0>或A < 1>。所以即使编译器也没有看到代码膨胀。

2

如果你想避免重复f可以使用template method pattern(不,不是那种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 
    } 
}; 
+0

这似乎与Benoît的建议相同,但知道模式的名称并了解它如何应用于函数是很好的。谢谢。 – Thomas 2010-09-09 12:51:42