【问题标题】:Alternate class design for providing correct pointer-like behavior (pointer to constant)?提供正确的类指针行为(指向常量的指针)的替代类设计?
【发布时间】:2011-11-20 03:19:31
【问题描述】:

我正在编写一组 C++ 参数化类,我对其中一些行为类似于指针的类感兴趣。特别是,我希望能够从具有非常量模板参数的对象创建具有常量模板参数的对象,但不能反过来。此示例代码应阐明我的意图:

int main() {
  myClass<int> mc_int;
  myClass<const int> mc_const_int;

  myClass<const int> mc1(mc_const_int); // This should compile.
  myClass<int> mc2(mc_int);             // This should compile.
  myClass<const int> mc3(mc_int);       // This should compile.
  myClass<int> mc4(mc_const_int);       // This should NOT compile.
}

我已经能够通过创建下一个类层次结构来实现这种特殊行为(为了便于阅读而进行了简化):

template <typename T>
class Base {

  // ...

protected:

  template <typename U>
  Base(const Base<U> &obj): _elem(obj._elem) {}

private:

  T _elem;

  friend class Base<const T>;
};

template <typename T>
class myClass: public Base<T> {

  // ...

public:

  template <typename U>
  myClass(const myClass<U> &obj): Base<const U>(obj) {}
};

它按预期工作,但我对这个设计并不完全满意,因为我只能从构造函数中检测到非常量模板参数,而不能从任何其他成员函数中检测到。

例如,如果我想用addAll() 方法创建一个容器类,我希望能够这样做:

int main() {
  Container<int> c_int;

  c_int.add(new int(1));
  c_int.add(new int(2));
  c_int.add(new int(3));

  Container<const int> c_const_int;

  c_const_int.addAll(c_int); // This should compile.
  c_int.addAll(c_const_int); // This should NOT compile.
}

但我不知道如何实现以前的行为。有没有人有替代设计的想法来实现我想要做的事情?有谁知道更深入讨论这个问题的链接?

提前致谢。

【问题讨论】:

    标签: c++ templates pointers constants class-design


    【解决方案1】:

    一种方法是通过部分模板专业化。您应该像往常一样为非const 类型定义类:

    template <typename T>
    struct MyClass {
        void f(T&);
    };
    

    然后定义一个专业

    template <typename T>
    struct MyClass<T const> {
        void f(T&);
        void f(T const&);
    };
    

    不幸的是,这会导致代码重复,但它应该允许你做你想做的事。当然,您也可以使用 MyClass&lt;T&gt;&amp;MyClass&lt;T const&gt;&amp; 的函数。

    【讨论】:

    • 非常感谢您的回答,这正是我想要的。我本来希望通过专门化方法而不是整个类来找到解决方法,但我认为考虑到我想要的类行为,没有办法做到这一点。可悲的是,我的课程已经从 500 行变成了 1000 行,但我不介意只要行为是理想的。
    【解决方案2】:

    我有点理解这个问题。您可能可以使用模板专业化。

    template <typename T>
    class container
    {
    public:
       template<typename U>
       void addAll(const container<U>& b ){}
    private:
       template<>
       void addAll(const container<int>&b); //No implementation
    };
    
    container<int> b;
    ....
    container<const int> a;
    a.addAll(b) ; //Give a link error, I can't understand why vc2010 compile and run this line though
    

    【讨论】:

      【解决方案3】:

      一种可能性是使用成员函数模板,启用它们以实现您想要的组合。

      #include <utility>
      
      template <class T, class U>
      struct const_convertible;
      
      template <class T>
      struct const_convertible<T, T>: std::true_type {};
      
      template <class T>
      struct const_convertible<T, const T>: std::true_type {};
      
      template <class T>
      struct const_convertible<const T, T>: std::false_type {};
      
      template <class T>
      class X
      {
      public:
         X() {}
         X(const X&) {} //copy constructor
         //conversion constructor as needed
         template <class U>
         X(const X<U>&, typename std::enable_if<const_convertible<U, T>::value, void>::type* = 0)
         {}
      
         template <class U>
         typename std::enable_if<const_convertible<U, T>::value, void>::type f(X<U>) {}
      };
      
      int main()
      {
         X<int> mut;
         X<const int> con;
      
         X<int> a(mut);
         //X<int> b(con);
         X<const int> c(mut);
         X<const int> d(con);
      
         mut.f(mut);
         //mut.f(con);
         con.f(mut);
         con.f(con);
      
         //X<double> doub;
         //doub.f(mut);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-23
        • 2018-08-09
        • 2013-01-04
        • 1970-01-01
        • 2011-08-04
        • 1970-01-01
        相关资源
        最近更新 更多