Pimpl习语:如果实现未知,使用什么size_type?

时间:2010-02-01 16:29:34

标签: c++ encapsulation return-type pimpl-idiom size-t

我有一个包含元素数组的类,我想给它一个GetSize成员函数。但是我应该给那个函数什么样的返回类型?

我正在使用pimpl习语,因此在头文件中不知道实现将用于存储元素的内容。所以我不能只说std::vector<T>::size_type,例如:

class FooImpl;

class Foo {
  FooImpl* impl_;
public:
  TYPE GetSize(); // what TYPE??
};

4 个答案:

答案 0 :(得分:1)

如果客户端代码只能看到Foo(这是pimpl习语的目的),那么在具体实现中定义特定的size_type是没有用的 - 它将不可见/无论如何,客户都可以访问。标准容器可以做到这一点,因为它们构建在所谓的“编译时多态”上,而您特别尝试使用[可能]运行时实现隐藏方法。

在您的情况下,唯一的选择是选择“应该足以满足所有可能的实现”的整数类型(例如unsigned long)并坚持使用它。

另一种可能性是使用uintptr_t类型,如果它在您的实现中可用(它在C99中标准化,但在C ++中没有标准化)。该整数类型应该涵盖程序可用的整个存储地址范围,这意味着它总是足以表示任何内存容器的大小。请注意,其他海报通常使用相同的逻辑,但错误地得出结论:此处使用的适当类型为size_t。 (这通常是由于缺乏非平坦内存模型实现的经验。)如果您的容器始终基于物理数组,size_t将起作用。但是,如果您的容器并不总是基于数组,那么size_t甚至不是远程正确的类型,因为它的范围通常小于非连续(非基于数组)的最大大小容器

但无论如何,你最终使用的是什么尺寸的regardelss,最好将它隐藏在typedef-name后面,就像在标准容器中完成一样。

答案 1 :(得分:1)

C ++中大小的泛型类型是size_t。我会用它。

我的意思是非技术性的通用。这与模板无关。

之前看起来像这样:When should I use std::size_t?

修改

经过多次讨论,我将略微修改我的答案。

如果size_t与指针一样宽,请使用size_t。如果不是,请使用与指针宽度相同的无符号整数。

答案 2 :(得分:0)

size_type通常用于隐藏整数类型(短对长与长对等)。只需定义自己的Foo::size_type

答案 3 :(得分:0)

您可以按照STL的标题,使size_type typedef依赖于FooImpl

template<typename T> class s_type {
    public:
    typedef size_t type; // good default
};

class FooImpl;

// I'm only doing this specialization to show how it's done
// not because I think it's needed.  In general I'd use size_t.
template<> class s_type<FooImpl> {
    public:
    typedef uintptr_t type;
};

class Foo {
  FooImpl* impl_;

  public:
  typedef size_type s_type<FooImpl>::type;
  size_type GetSize();
};