我有一个包含元素数组的类,我想给它一个GetSize
成员函数。但是我应该给那个函数什么返回类型呢?
我正在使用 pimpl 习惯用法,因此在头文件中不知道实现将使用什么来存储元素。所以我不能只说std::vector<T>::size_type
,例如:
class FooImpl;
class Foo {
FooImpl* impl_;
public:
TYPE GetSize(); // what TYPE??
};
我有一个包含元素数组的类,我想给它一个GetSize
成员函数。但是我应该给那个函数什么返回类型呢?
我正在使用 pimpl 习惯用法,因此在头文件中不知道实现将使用什么来存储元素。所以我不能只说std::vector<T>::size_type
,例如:
class FooImpl;
class Foo {
FooImpl* impl_;
public:
TYPE GetSize(); // what TYPE??
};
如果客户端代码只能看到Foo
(这是 pimpl idiom 的目的),那么size_type
在具体实现中定义一个特定的就没有用 - 无论如何客户端都不会看到/访问它。标准容器可以做到这一点,因为它们建立在所谓的“编译时多态性”之上,而您专门尝试使用 [可能] 运行时实现隐藏方法。
在您的情况下,唯一的选择是选择“对于所有可能的实现应该足够”的整数类型(例如unsigned long
,例如)并坚持下去。
另一种可能性是使用该uintptr_t
类型,如果它在您的实现中可用(它在 C99 中标准化,但在 C++ 中没有)。这个整数类型应该覆盖程序可用的整个存储地址范围,这意味着它总是足以表示任何内存容器的大小。请注意,其他发帖人经常使用相同的逻辑,但错误地得出结论,此处使用的适当类型是size_t
. (这通常是由于缺乏非平面内存模型实现经验的结果。)如果您的容器始终基于物理数组,size_t
则可以使用。但是,如果您的容器并不总是基于数组,size_t
甚至不是在这里使用的正确类型,因为它的范围通常小于非连续(非基于数组)容器的最大大小。
但无论如何,无论您最终使用什么大小,最好将其隐藏在 typedef-name 后面,就像在标准容器中所做的那样。
C++ 中大小的通用类型是 size_t。我会用那个。
我的意思是非技术意义上的通用。这与模板无关。
以前好像出现过这样的情况:我什么时候应该使用 std::size_t?
编辑
经过多次讨论,我将稍微修改我的答案。
如果 size_t 与指针一样宽,则使用 size_t。如果不是,请使用与指针宽度相同的无符号整数。
size_type 通常用于隐藏整数类型(short vs. long vs. long long 等)。只需定义自己的Foo::size_type
.
您可以遵循 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();
};