【问题标题】:C++ enable_if (or workaround) for member operator成员运算符的 C++ enable_if(或解决方法)
【发布时间】:2011-04-13 13:51:04
【问题描述】:
template<typename T>
struct foo
{
    T* p;
    foo(T* x) : p(x) {}
    ~foo() { if(p) delete p; }
    T& operator*() const { return *p; }
};

int main()
{
    foo<int>  i(new int);
    foo<void> v(new int);   // <= illegal use of type 'void'
}

如果 T = void 那么我不想实现 operator*()。我怎样才能做到这一点?我不想专门化这门课,因为我的课还有很多其他的方法。

PS:请注意,这只是解释我的问题的一个例子。

【问题讨论】:

    标签: c++ templates operators typetraits


    【解决方案1】:

    您可以将所有其他方法(与T==void 配合得很好)移动到一个基类中,并使foo 派生自它。那么foo可以专门化为不为T==void声明operator*

    template <typename T>
    struct foobase {
    
      T* p;
      foobase(T* x) : p(x) {}
      ~foobase() { if(p) delete p; }
    
    };
    
    template <typename T>
    struct foo : foobase<T> {
      T& operator*() const { return *p; }
    };
    
    template<> 
    struct foo<void> : foobase<void> {
    
    };
    

    【讨论】:

      【解决方案2】:

      C++11 标准为 std::unique_ptr 解决了这个问题,如下所示:

      typename std::add_lvalue_reference<T>::type
          operator*() const { return *p; }
      

      【讨论】:

      • 嗯,我也可以在 C++ 中使用它: typename std::add_reference::type operator* () const { return *p; }
      【解决方案3】:

      这样:

      template<typename T>
      struct foo_base
      {
          T* p;
          foo(T* x) : p(x) {}
          ~foo() { if(p) delete p; }
      
          // other methods …
      };
      
      template<typename T>
      struct foo : foo_base<T>
      {
          T& operator*() const { return *p; }
      };
      
      template<>
      struct foo<void> : foo_base<void>
      {
      };
      

      【讨论】:

      • (+1) 有趣的是,当我在我的初始响应中添加一个代码示例时,我们似乎有些重叠,除了我选择了foobase 而不是foo_base。哦,好吧.. :-)
      • @Alexander 我没有给出额外的解释:(但我的代码格式更好:)
      【解决方案4】:

      怎么样

      typename disable_if<is_void<T>, T>::type& operator* () const { return *p;}
      

      还是我在这里遗漏了一些明显的东西?

      【讨论】:

      • disable_if 否则我同意。
      • 那不行,因为当'T = void'时,'T&'是不合法的:'abstract declarator' : 非法使用'void'类型
      • SFINAE 仅适用于模板函数,即它不适用于模板类的非模板成员函数,例如在这种情况下。您还可以模板化成员函数并检查类型是否与 T 相同,但这并不完全优雅。
      【解决方案5】:

      这个解决方案是什么:

      template<typename T>
      struct foo
      {
          T* p;
          foo(T* x) : p(x) {}
          ~foo() { if(p) delete p; }
      
          template<typename U> struct impl { U& deref(U* p) { return *p; } };
          template<> struct impl<void> { void deref(void* p) { } };
      
          typename boost::conditional<std::is_void<T>::value, T, typename std::add_reference<T>::type>::type operator*() const
          {
              static_assert(!std::is_void<T>::value, "illegal use of type 'void'");
              return impl<T>().deref(p); 
          }
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-11
        • 1970-01-01
        • 1970-01-01
        • 2012-01-23
        • 1970-01-01
        • 2012-10-12
        • 2011-07-08
        • 1970-01-01
        相关资源
        最近更新 更多