【问题标题】:C++11: conditional compilation: membersC++11:条件编译:成员
【发布时间】:2013-03-18 09:42:13
【问题描述】:

我正在尝试使用条件成员创建一个结构,这意味着不同的成员仅存在于特定的专业化中。但是,我希望这些课程尽可能快。我尝试了三种不同的方式:

方式一:

 template<typename T, bool with_int = false>
 struct foo
 {
     template<typename... Args>
     foo(Args&&... args) : m_t(forward<Args>(args)...)
     {}

     T m_t;
 }

 template<typename T>
 struct foo<T, true>
 {
     template<typename... Args>
     foo(Args&&... args) : m_t(forward<Args>(args)...), m_id(0)
     {}

      T m_t;
      int m_id;
 };
  • 缺点:每个专业都有重复的代码。

方式 2:

 template<typename T, bool with_int = false>
 struct foo
 {
     template<typename... Args>
     foo(Args&&... args) : m_t(forward<Args>(args)...)
     {}

     virtual ~foo() {}

     T m_t;
 }

 template<typename T>
 struct foo<T, false> : public foo<T>
 {
      using foo<T>::foo;

      int m_id = 0;
 };
  • 优点:代码少。
  • 缺点:使用 vtables/inheritance/etc:更多时间用于构建或访问成员?但是,在其他方面,我不会假装使用“引用”来访问基类。这种方法的真正优点或缺点是什么?

方式 3

 using nil_type = void*;
 using zero_type = nil_type[0];

 template<typename T, bool with_int = false>
 struct foo
 {
    template<typename... Args, typename = typename enable_if<with_int>::type>
    foo(Args&&... args) : m_t(forward<Args>(args)...), m_int(0)
    {}

    template<typename... Args, typename = typename enable_if<!with_int>::type>
    foo(Args&&... args) : m_t(forward<Args>(args)...)
    {}        

    T m__t;
    typename conditional<with_int, int, zero_type>::type m_int;
 };
  • Ventages:编写一次代码;当with_intfalse 时,m_int 字段的大小为 0(几乎使用 gcc 4.7.2)。
  • 优点:更多地使用模板(降低可读性)并且我不确定编译器如何处理大小为 0 的成员。我确实不知道大小为 0 的字段在多大程度上是危险的或有意义的。重复构造函数,但也许这是可以避免的。

什么是最好的方法或方法?

【问题讨论】:

  • OT,但我很确定包含双下划线的名称是为编译器保留的,因此您应该使用 m_intm_t
  • 我认为只有成员开始有双下划线,但不包含它。
  • 不行,看答案hereEach name that contains a double underscore (_ _) or begins with an underscore followed by an uppercase letter (2.11) is reserved to the implementation for any use.
  • 请注意,您不能拥有大小为 0 的成员,编译器仍会为其分配非零大小。 &Var1 == &Var2 当且仅当 Var1 和 Var2 是同一个变量。任何大小为 0 的变量都会违反这一点。
  • 那么,sizeof 撒谎? sizeof 说我 zero_type 的大小为 0,foo&lt;int, false&gt; 的大小为 4,foo&lt;int, true&gt; 的大小为 8。与 struct { char m[0] }; 相同:sizeof 返回 0。

标签: c++ c++11 conditional-compilation


【解决方案1】:

你考虑过继承吗?

template< bool >
struct foo_int_base
{
  // stuff without the int
  void f(); // does not use m_id
};

template<>
struct foo_int_base< true >
{
  // stuff with the int
  int m_id = 0;
  void f(); // uses m_id
};

template< typename T, bool with_int = false >
struct foo : foo_int_base< with_int >
{
  // common stuff here
};

【讨论】:

  • 在我的第二种方法中考虑使用继承。请阅读下面的内容和我的问题。
  • 您的方法不同,它使用virtual (这是有成本的),它试图从非整数大小写中派生整数大小写,恕我直言,这会使事情变得更加复杂并且不提供明确的分离。但这只是我的建议,我不知道这是否适合你。
  • 这是正确的解决方案。请注意,foo_int_base&lt;false&gt;additional 大小为 0(当然在优化构建中)。与成员不同,基类子对象的大小可以为零。
猜你喜欢
  • 2018-08-25
  • 2012-09-25
  • 1970-01-01
  • 1970-01-01
  • 2011-10-21
相关资源
最近更新 更多