C++ STL - Why std::forward_list has no size() method?

N2543 is the proposal, and it has a detailed discussion about size().

The choice between Option 3 [not providing size()] and Option 2 [providing a O(1) size()] is more a matter of judgment. I have chosen Option 3 for the same reason that I chose insert-after instead of insert-before: Option 3 is more consistent with the goal of zero overhead compared to a hand-written C-style linked list. Maintaining a count doubles the size of a forward_list object (one word for the list head and one for the count), and it slows down every operation that changes the number of nodes. In most cases this isn't a change in asymptotic complexity (the one change in asymptotic complexity is in one of the forms of splice), but it is nonzero overhead. It's a cost that all users would have to pay for, whether they need this feature or not, and, for users who care about maintaining a count, it's just as easy to maintain it outside the list, by incrementing the count with every insert and decrementing it with every erase, as it is to maintain the count within the list.


The STL containers have traditionally/intelligently removed the features of data structures that do not perform well in terms of time and space.

Adding Quote from "The C++ standard library - a Tutorial and Reference" by Nicolai M. Josuttis.

A std::forward_list does not provide a size() member function. This is a consequence of omitting features that create time or space overhead relative to a handwritten singly linked list.


i wonder if the standard committee considered a mix-in as template parameters that can add maintenance of an optional size member to the list classes? This would have allowed the class to have an optional element count, without loss of generality.

like this

class HasSize
{ 
public:
   HasSize() : size_(0) { } 

   void addSize(size_t add) { size_ += add; }

   bool has_size() { return true; }

   size_t size() { return size_; }

   size_t size_;
};

class NoSize
{ 
public:
   void addSize(size_t add) { }

   bool has_size() { return false; }

   size_t size() { return 0; }
};

template<type T, type Allocator, type Sz = HasSize>
class forward_list
{

    void push_back( T &arg )
    {
         ...
         opt_.addSize( 1 );
    }

    size_t size()
    {
       if (opt_.has_size())
          return opt_.size();
       else
          return std::distance(begin(), end()); 
    }

    Sz opt_;
};

/this question was marked as duplicated, so adding it here/