开发者

How do I implement array::max_size()?

开发者 https://www.devze.com 2023-02-12 04:18 出处:网络
I am building my own array<T, n> class template for fun and education. The C++0x standard draft specifies a member function max_size() 开发者_开发知识库for all containers as distance(begin(), en

I am building my own array<T, n> class template for fun and education. The C++0x standard draft specifies a member function max_size() 开发者_开发知识库for all containers as distance(begin(), end()) "for the largest possible container". How do I implement this member function for arrays? Do I simply return std::numeric_limits<std::size_t>::max(), or should the result depend on the element type?


Hmm, both std::array from current g++ and boost::array return n from max_size():

#include <array>
#include <boost/array.hpp>
#include <iostream>

int main()
{
    std::array<int, 11> foo;
    std::cout << foo.max_size() << std::endl;   // prints 11

    boost::array<int, 11> bar;
    std::cout << bar.max_size() << std::endl;   // prints 11
}


If your array is fixed-size, just return the size (n in your example), since that is also the maximum size.


I agree that the draft is somewhat lacking here.

It is unclear whether container here references:

  • any container
  • any container of this family
  • any container of a given instance of this family

Unlike @Jerry I would lean toward the latter option.

Looking at basic_string::append, the description states:

Throws: length_error if size() + n > max_size()

With this remark, I think that the Standard puts its foot in the door for the specification of generic algorithms whose behavior would differ based on whether or not the Container they are operating on can be expanded or not, which can be checked with max_size.

As such, a Container should logically returns its maximum length.

Therefore, std::size_t std::array<T,n>::max_size() const { return n; } is the logical choice.

Note that this same max_size definition would logically be applicable to fixed-sized allocators (and notably, stack-based allocators as written by Howard Hinnant).


It should be n, as array implies fixed-size. And here the fixed size is n.

If it's anything other than n, then what does n stand for in array<T, n>?


Yes, I think it should normally depend on the element size, so you'd typically have something like: std::numeric_limits<std::size_t>::max()/sizeof(T). Otherwise, you're giving a size that's typically going to be considerably larger than is actually possible.

Edit: Based on table 93, I have to disagree with Nawaz and Jeremiah Willcock. max_size is clearly described as the size for the largest possible container, not the largest size to which a specific container could expand.


The documentation for max_size says the function should return "the maximum theoretically possible value of n, for which the call allocate(n, 0) could succeed," where n is the number of objects.

The STL containers (e.g. - std::vector, std::map, or std::list) use max_size to calculate container size in terms of object count, not byte count. Therefore, max_size() should not return the number of bytes available on the operating system, but use the number of available bytes to calculate the number of objects the allocator can hold.

If you wrote an allocator class for STL containers, you could implement the max_size() function like this to provide an accurate object count instead of over-estimating by using std::numeric_limits<size_type>::max().

size_type max_size() const
{
    const unsigned long long bytesAvailable = GetTotalAvailableMemory();
    const unsigned long long maxPossibleObjects = bytesAvailable / sizeof(value_type);
    return maxPossibleObjects;
}

You can implement the GetTotalAvailableMemory() like these functions depending on your operating system. Either will return the number of unallocated bytes which a program's process may use.

#if defined(unix) || defined(__unix__) || defined(__unix)

#include <unistd.h>

unsigned long long GetTotalAvailableMemory()
{
    const long pageCount = sysconf( _SC_PHYS_PAGES );
    const long pageSize = sysconf( _SC_PAGE_SIZE );
    const unsigned long long totalBytes = pageCount * pageSize;
    return totalBytes;
}

#endif

#if defined(_WIN64) || defined(_WIN64)

#include <windows.h>

unsigned long long GetTotalAvailableMemory()
{
    MEMORYSTATUSEX status;
    status.dwLength = sizeof( status );
    GlobalMemoryStatusEx( &status );
    return status.ullAvailVirtual;
}

#endif
0

精彩评论

暂无评论...
验证码 换一张
取 消