在C ++中隐藏用户的参数类型

时间:2014-08-03 04:58:45

标签: c++ c++11 casting type-conversion

假设我正在编写容器类template <typename T> class MyContainer,并且由于某种原因,我想传递类型T的对象,其类型对用户是隐藏的。特别是,我想确保MyContainer::Foo的所有输入首先通过MyContainer::HideType

template <typename T>
class MyContainer {
 public:
  ... constructors and stuff...

  HidesType& HideType(T&);      
  T& UnhideType(HidesType&);

  void Foo(HideType&);

  ... some other stuff...
};

现在我想知道HidesType可以/应该是什么。一些选项是:

struct HidesType { 
  HidesType(T& data) : data_(data) { }
  T& data_; 
};
HidesType HideType(T& data) { return HidesType(data); }

union HidesType { T data_; };
HidesType& HideType(T& data) { return reinterpret_cast<HidesType&>(data); }

class HidesType : public T { };
HidesType& HideType(T& data) { return static_cast<HidesType&>(data); }

第一个问题是用户无法将T个对象保留为

MyContainer<T>::HidesType tmp(HideType(t_obj));

因为tmp超出范围后t_obj将无效。另外,我不确定编译器是否会完全优化HidesType。

第二个问题是我不知道reinterpret_cast是否安全(例如,是否会出现任何对齐问题?)。

第三个问题是,T可能会被标记为final,而HidesType&amp;皈依T&amp;隐式。

任何想法或建议都将不胜感激。

修改

隐藏的主要目的是使HidesType抽象并与T区分开来。 解释导致这个问题的所有背景将是很麻烦的。现在,让我们假设函数MyContainer::Foo基本上作为输入T,但是,我不希望用户知道/使用它,特别是接口可能在将来发生变化。

正确的用例可能是:

MyContainer<T>::HidesType handle = MyContainer<T>::HideType(t_obj);
... do something ...
... perhaps t_obj.~T(); ...
... do something ...
my_container.Foo(handle);

无用的用例:

MyContainer<T>::HidesType handle = MyContainer<T>::HideType(t_obj);
... do something ...
my_container.Foo(some_other_t_obj);

2 个答案:

答案 0 :(得分:0)

您希望类型H只能由MyContainer<T>实例化或修改。

实现这一目标的简单方法是使用private构造函数和赋值运算符的类类型,移动构造函数除外,MyContainer<T>friend

您可以move指定的T对象,既可以提高效率,也可以不必要地将其设置为可复制。如果是,那么H将不保证是可复制的。但是,正如我所看到的,它应该是可以移动的。

答案 1 :(得分:0)

您可以执行以下操作:

template <typename T>
class MyContainer {
public:
    class HandleType {
    public:
        friend class MyContainer;

        HandleType(const HandleType& rhs) = default;
        HandleType(HandleType&& rhs) = default;
        HandleType& operator =(const HandleType& rhs) = default;
        HandleType& operator =(HandleType&& rhs) = default;
    private:
        // only MyContainer can construct this class
        explicit HandleType(const T& t) : t(t) {}

    private:
        T t;
    };

    HandleType HideType(const T& t) { return HandleType(t); }
    T& UnhideType(HandleType& handle) { return handle.t; }

    void Foo(HandleType&);
};