C++ fixed size string

Why is something like this not part of the C++ stdlib, only available in many different 3rd party libraries?

One example, header only, with a vcpkg package: fixed_string

https://github.com/unterumarmung/fixed_string

Well, maybe I 'spoke' too soon, it looks like there is a proposal for a C++ stdlib std::fixed_string (std::basic_fixed_string):

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3094r0.html

For those here who are more in-tuned and knowledgeable about the standards committee's inner workings might this actually become a part of C++26?
Last edited on
Maybe I'm missing something crucial to non-adoption, something really basic.

Until std::array was added to the stdlib it was either use regular C style arrays or clamp down on the dynamism of a std::vector. Why not have the same for a C++string? A thin veneer over a C string array.
bloat? The only reason I can think of for it is a binary file with fixed sized records type setup, and its trivial to roll your own if you need it. Do you even need much more than a std string with a new assignment operator (which truncates if it exceeds your limit)? Or is your goal to avoid dynamic memory entirely, some performance need? Layering over C string would at best have equal performance at risk of slightly worse, it would need a ground up implementation if speed is the need.
Last edited on
So why adopt std::array if size and speed (and more) are considerations to not adopt std::fixed_string?

Yes, it is trivial to "roll your own" fixed_string, but that can potentially lead to incompatibility with differing stdllib versions.

The proposal states quite clearly one of the reasons for making fixed_string part of the stdlib:

Having such a type in the C++ standard library will prevent reinventing the wheel by the community and reimplementing it in every project that handles text at compile-time.

I am a profound believer in not reinventing a flat wheel if the stdlib has the ability. I especially like when some potential problem can be ferreted out at compile time.

One of the nice features of having a fixed size array as part of the C++ stdlib is the seamless way it has a similar functional interface to the other C++ containers and linkage with stdlib algorithms. std::fixed_string could offer the same benefits.

I would simply prefer to use an already available C++ stdlib solution if and when I need it. One of the benefits and detriments of being a self-taught programming hobbyist.

My Two Pence....
Speaking about bloat, would a std::fixed_string be any more bloaty and resource wasteful than the current multitude of 3rd party libraries? I seriously doubt it. Just because something proposed is not yet part of the standard doesn't make it de-facto worse than existing non-standard solutions.
std::array was designed to be a zero-overhead wrapper for C-style array while providing the value like semantics of other C++ containers. Why would std::fixed_string be any different by being excessively bloaty and resource wasteful?

std::array is basically defined as:
1
2
3
4
5
6
7
8
template<typename T, size_t N>
struct array
{
    T _data[N];
    T& operator[](size_t);
    const T& operator[](size_t) const;
    // other member functions and typedefs
};

std::fixed_string could be a template specialization of std::array for working with strings/characters and a class name change. The details of dealing with a string array are different than a regular array, though.

Passing a C array, string or otherwise, into a non-template function effectively devolves the array to a pointer so the function doesn't know what the size of the array unless passed as a separate parameter. std::fixed_string would "remember" its size, just as std::array does.

Yes, std::array is an aggregate, so std::fixed_string likely would be as well.

A C-style array and its elements are allocated on the stack unless new is used. A std::array's elements are stack-based as well, and can't have the elements on the free store/heap.

Hiding all the messy details of dealing with read-only C-style arrays in a C++ wrapper would be IMO advantageous since the proposal appears to have a similar interface to std::string.

If you need the ability to change the contents using a std::string would be the thing to do.
Its not 'more' bloaty, but the language is getting bloated just the same. I am a little concerned with the sheer number of more and more exotic objects built into the core language. Maybe this is how all modern languages go, but my question really was "do we need this one".

It fits the patterns we have for sure ... I agree with everything you said, I just am not sure that, if we MUST add more widgets to the language, this is the most needed one? Or even in the top 10? Or are we doomed to grow the language with hundreds more.. ?

Maybe I am feeling overwhelmed this week :)
So you'd rather have tons of 3rd party libraries instead, or custom code that is a PITA to keep updated when other things change around it. Not me.

Clearly the Standards Committee members believed the additions justified being added.

To show how simple a construct std::fixed_string might be look at the library I linked to earlier: https://github.com/unterumarmung/fixed_string

A header only file less than 700 lines of easy to read well formatted code.

And the fixed_string can be modified:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>

#include <fixed_string.hpp>

int main( )
{
   constexpr fixstr::fixed_string first  = "Hello, ";
   constexpr fixstr::fixed_string second = "World!";
   constexpr auto                 result = first + second; // "Hello, World!"
   std::cout << result << '\t' << first.size( ) << '\t' << second.size( )<< '\t' << result.size( ) << '\n';

   fixstr::fixed_string test = "Test";
   std::cout << test << '\t' << test.size( ) << '\n';

   test = "More";
   std::cout << test << '\t' << test.size( ) << '\n';

   for ( auto& itr : test )
   {
      itr = 'a';
   }
   std::cout << test << '\n';

   for ( auto itr { test.begin( ) }; itr != test.end( ); ++itr )
   {
      *itr = 'b';
   }
   std::cout << test << '\n';

   for ( size_t itr { }; itr < test.size( ); ++itr )
   {
      test[itr] = 'c';
   }
   std::cout << test << '\n';
}

Hello, World!   7       6       13
Test    4
More    4
aaaa
bbbb
cccc

This 3rd party fixed_string can be used with std::format or std::print/std::println, the fixed_string object merely needs to expose its underlying data.

std::cout << std::format( "{}, {}, {}, {}\n", result.data( ), first.size( ), second.size( ), result.size( ) );

A lot of the proposed functionality is already baked into the pie with this library, so not a lot of work to add it IMO.

The Standards Committee has shamelessly stolen library code before, peed on it and made it C++ stdlib. A couple of examples, the {fmt} lib and a whole lot of Boost libraries.
Topic archived. No new replies allowed.