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

发布于 2024-08-20 13:32:21 字数 277 浏览 12 评论 0原文

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

我使用的是 pimpl 习惯用法,因此在头文件中不知道实现将使用什么来存储元素。所以我不能只说 std::vector::size_type,例如:

class FooImpl;

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

I have a class that holds an array of elements, and I want to give it a GetSize member function. But what return type should I give that function?

I'm using the pimpl idiom, and so in the header file it is not known what the implementation will use to store the elements. So I cannot just say std::vector<T>::size_type, for example:

class FooImpl;

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

小矜持 2024-08-27 13:32:22

C++ 中大小的通用类型是 size_t。我会用那个。

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

看起来这个问题之前出现过:何时应该使用 std::size_t?

编辑

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

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

The generic type for sizes in C++ is size_t. I'd use that.

I mean generic in the non-technical sense. This has nothing to do with templates.

Looks like this came up before: When should I use std::size_t?

edit

After much discussion, I'm going to slightly amend my answer.

If the size_t is as wide as the pointer, use size_t. If not, use an unsigned int of the same width as the pointer.

断念 2024-08-27 13:32:22

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

size_type's are usually used to hide the integer type (short vs. long vs. long long etc). Just define your own Foo::size_type.

酒几许 2024-08-27 13:32:22

您可以遵循 STL 的指导,将 size_type 设为依赖于 FooImpltypedef

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();
};

You could follow the STL's lead and make size_type a typedef that relies on 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();
};
李白 2024-08-27 13:32:21

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

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

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

但无论如何,无论您最终使用什么大小,最好将其隐藏在 typedef 名称后面,就像在标准容器中所做的那样。

If the client code can only see Foo (which is the purpose of pimpl idiom), then there's no use in define a specific size_type in the concrete implementation - it won't be visible/accessible to the client anyway. Standard containers can do that since they are built on so called "compile-time polymorphism", while you are specifically trying to use a [potentially] run-time implementation hiding method.

In your situation the only choice would be to choose an integer type that "should be enough for all possible implementations" (like unsigned long, for example) and stick with it.

Another possibility is to use the uintptr_t type, if it is available in your implementation (it is standardized in C99, but not in C++). This integer type is supposed to cover the entire storage address range available to the program, which means that it will always be sufficient for representing the size of any in-memory container. Note, that other posters often use the same logic, but incorrectly arrive at the conclusion that the appropriate type to use here is size_t. (This is usually a result of lack of experience with non-flat memory model implementatioons.) If your containers are always based on physical arrays, size_t will work. However, if your containers are not always array-based, size_t is not even remotely the correct type to use here, since its range is generally smaller than the maximum size of a non-continuous (non-array-based) container.

But in any case, regardelss of what size you are end up using, it is a good idea to hide it behind a typedef-name, just like it is done in standard containers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文