Files
boost_static_string/include/boost/fixed_string/fixed_string.hpp
Vinnie Falco c0ffc9f665 Tidying
2019-09-16 08:32:32 -07:00

1286 lines
29 KiB
C++

//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/fixed_string
//
#ifndef BOOST_FIXED_STRING_FIXED_STRING_HPP
#define BOOST_FIXED_STRING_FIXED_STRING_HPP
#include <boost/fixed_string/config.hpp>
#include <boost/fixed_string/detail/fixed_string.hpp>
#include <algorithm>
#include <cstdint>
#include <initializer_list>
#include <iosfwd>
#include <stdexcept>
#include <string>
#include <type_traits>
namespace boost {
namespace fixed_string {
/** A fixed-capacity string.
These objects behave like `std::string` except that the storage
is not dynamically allocated but rather fixed in size, and
stored in the object itself.
These strings offer performance advantages when an algorithm
can execute with a reasonable upper limit on the size of a value.
@see to_fixed_string
*/
template<
std::size_t N,
typename CharT = char,
typename Traits = std::char_traits<CharT>>
class fixed_string
{
template<std::size_t, class, class>
friend class fixed_string;
void
term()
{
Traits::assign(s_[n_], 0);
}
std::size_t n_;
CharT s_[N+1];
public:
//--------------------------------------------------------------------------
//
// Member types
//
//--------------------------------------------------------------------------
using traits_type = Traits;
using value_type = typename Traits::char_type;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;
using const_pointer = value_type const*;
using const_reference = value_type const&;
using iterator = value_type*;
using const_iterator = value_type const*;
using reverse_iterator =
std::reverse_iterator<iterator>;
using const_reverse_iterator =
std::reverse_iterator<const_iterator>;
/// The type of `string_view` returned by the interface
using string_view_type =
basic_string_view<CharT, Traits>;
//--------------------------------------------------------------------------
//
// Constants
//
//--------------------------------------------------------------------------
/// Maximum size of the string excluding any null terminator
static std::size_t constexpr static_capacity = N;
/// A special index
static constexpr size_type npos = size_type(-1);
//--------------------------------------------------------------------------
//
// Construction
//
//--------------------------------------------------------------------------
/// Default constructor (empty string).
fixed_string();
/** Construct with count copies of character `ch`.
The behavior is undefined if `count >= npos`
*/
fixed_string(
size_type count,
CharT ch);
/// Construct with a substring (pos, other.size()) of `other`.
template<std::size_t M>
fixed_string(
fixed_string<M, CharT, Traits> const& other,
size_type pos);
/// Construct with a substring (pos, count) of `other`.
template<std::size_t M>
fixed_string(
fixed_string<M, CharT, Traits> const& other,
size_type pos,
size_type count);
/// Construct with the first `count` characters of `s`, including nulls.
fixed_string(
CharT const* s,
size_type count);
/// Construct from a null terminated string.
fixed_string(
CharT const* s);
/// Construct from a range of characters
template<class InputIt>
fixed_string(
InputIt first,
InputIt last
#ifndef GENERATING_DOCUMENTATION
, typename std::enable_if<
detail::is_input_iterator<InputIt>::value,
iterator>::type* = 0
#endif
);
/// Copy constructor.
fixed_string(
fixed_string const& other);
/// Copy constructor.
template<std::size_t M>
fixed_string(
fixed_string<M, CharT, Traits> const& other);
/// Construct from an initializer list
fixed_string(
std::initializer_list<CharT> init);
/// Construct from a `string_view`
explicit
fixed_string(
string_view_type sv);
/** Construct from any object convertible to `string_view_type`.
The range (pos, n) is extracted from the value
obtained by converting `t` to `string_view_type`,
and used to construct the string.
*/
template<class T
#ifndef GENERATING_DOCUMENTATION
, class = typename std::enable_if<
std::is_convertible<T, string_view_type>::value>::type
#endif
>
fixed_string(
T const& t,
size_type pos,
size_type n);
//--------------------------------------------------------------------------
//
// Assignment
//
//--------------------------------------------------------------------------
/// Copy assignment.
fixed_string&
operator=(
fixed_string const& s)
{
return assign(s);
}
/// Copy assignment.
template<std::size_t M>
fixed_string&
operator=(
fixed_string<M, CharT, Traits> const& s)
{
return assign(s);
}
/// Assign from null-terminated string.
fixed_string&
operator=(
CharT const* s);
/// Assign from single character.
fixed_string&
operator=(
CharT ch)
{
return assign_char(ch,
std::integral_constant<bool, (N>0)>{});
}
/// Assign from initializer list.
fixed_string&
operator=(
std::initializer_list<CharT> init)
{
return assign(init);
}
/// Assign from `string_view_type`.
fixed_string&
operator=(
string_view_type sv)
{
return assign(sv);
}
/// Assign `count` copies of `ch`.
fixed_string&
assign(
size_type count,
CharT ch);
/// Assign from another `fixed_string`
fixed_string&
assign(
fixed_string const& s);
/// Assign from another `fixed_string`
template<std::size_t M>
fixed_string&
assign(
fixed_string<M, CharT, Traits> const& s)
{
// VFALCO this could come in two flavors,
// N>M and N<M, and skip the exception
// check when N>M
return assign(s.data(), s.size());
}
/// Assign `count` characters starting at `npos` from `other`.
template<std::size_t M>
fixed_string&
assign(
fixed_string<M, CharT, Traits> const& s,
size_type pos,
size_type count = npos);
/// Assign the first `count` characters of `s`, including nulls.
fixed_string&
assign(
CharT const* s,
size_type count);
/// Assign a null terminated string.
fixed_string&
assign(
CharT const* s)
{
return assign(s, Traits::length(s));
}
/// Assign from an iterator range of characters.
template<typename InputIt>
#ifdef GENERATING_DOCUMENTATION
fixed_string&
#else
typename std::enable_if<
detail::is_input_iterator<InputIt>::value,
fixed_string&>::type
#endif
assign(
InputIt first,
InputIt last);
/// Assign from initializer list.
fixed_string&
assign(
std::initializer_list<CharT> init)
{
return assign(init.begin(), init.end());
}
/// Assign from `string_view_type`.
fixed_string&
assign(
string_view_type s)
{
return assign(s.data(), s.size());
}
/** Assign from any object convertible to `string_view_type`.
The range (pos, n) is extracted from the value
obtained by converting `t` to `string_view_type`,
and used to assign the string.
*/
template<class T>
#if GENERATING_DOCUMENTATION
fixed_string&
#else
typename std::enable_if<std::is_convertible<T,
string_view_type>::value, fixed_string&>::type
#endif
assign(
T const& t,
size_type pos,
size_type count = npos);
//--------------------------------------------------------------------------
//
// Element access
//
//--------------------------------------------------------------------------
/// Access specified character with bounds checking.
reference
at(size_type pos);
/// Access specified character with bounds checking.
const_reference
at(size_type pos) const;
/// Access specified character.
reference
operator[](size_type pos)
{
return s_[pos];
}
/// Access specified character.
const_reference
operator[](size_type pos) const
{
return s_[pos];
}
/// Accesses the first character.
CharT&
front()
{
return s_[0];
}
/// Accesses the first character.
CharT const&
front() const
{
return s_[0];
}
/// Accesses the last character.
CharT&
back()
{
return s_[n_-1];
}
/// Accesses the last character.
CharT const&
back() const
{
return s_[n_-1];
}
/// Returns a pointer to the first character of a string.
CharT*
data()
{
return &s_[0];
}
/// Returns a pointer to the first character of a string.
CharT const*
data() const
{
return &s_[0];
}
/// Returns a non-modifiable standard C character array version of the string.
CharT const*
c_str() const
{
return data();
}
/// Convert a static string to a `string_view_type`
operator string_view_type() const
{
return basic_string_view<
CharT, Traits>{data(), size()};
}
//--------------------------------------------------------------------------
//
// Iterators
//
//--------------------------------------------------------------------------
/// Returns an iterator to the beginning.
iterator
begin()
{
return &s_[0];
}
/// Returns an iterator to the beginning.
const_iterator
begin() const
{
return &s_[0];
}
/// Returns an iterator to the beginning.
const_iterator
cbegin() const
{
return &s_[0];
}
/// Returns an iterator to the end.
iterator
end()
{
return &s_[n_];
}
/// Returns an iterator to the end.
const_iterator
end() const
{
return &s_[n_];
}
/// Returns an iterator to the end.
const_iterator
cend() const
{
return &s_[n_];
}
/// Returns a reverse iterator to the beginning.
reverse_iterator
rbegin()
{
return reverse_iterator{end()};
}
/// Returns a reverse iterator to the beginning.
const_reverse_iterator
rbegin() const
{
return const_reverse_iterator{cend()};
}
/// Returns a reverse iterator to the beginning.
const_reverse_iterator
crbegin() const
{
return const_reverse_iterator{cend()};
}
/// Returns a reverse iterator to the end.
reverse_iterator
rend()
{
return reverse_iterator{begin()};
}
/// Returns a reverse iterator to the end.
const_reverse_iterator
rend() const
{
return const_reverse_iterator{cbegin()};
}
/// Returns a reverse iterator to the end.
const_reverse_iterator
crend() const
{
return const_reverse_iterator{cbegin()};
}
//--------------------------------------------------------------------------
//
// Capacity
//
//--------------------------------------------------------------------------
/// Returns `true` if the string is empty.
bool
empty() const
{
return n_ == 0;
}
/// Returns the number of characters, excluding the null terminator.
size_type
size() const
{
return n_;
}
/// Returns the number of characters, excluding the null terminator.
size_type
length() const
{
return size();
}
/// Returns the maximum number of characters that can be stored, excluding the null terminator.
size_type constexpr
max_size() const
{
return N;
}
/** Reserves storage.
This actually just throws an exception if `n > N`,
otherwise does nothing since the storage is fixed.
*/
void
reserve(std::size_t n);
/// Returns the number of characters that can be held in currently allocated storage.
size_type constexpr
capacity() const
{
return max_size();
}
/** Reduces memory usage by freeing unused memory.
This actually does nothing, since the storage is fixed.
*/
void
shrink_to_fit()
{
}
//--------------------------------------------------------------------------
//
// Operations
//
//--------------------------------------------------------------------------
/// Clears the contents.
void
clear();
fixed_string&
insert(
size_type index,
size_type count,
CharT ch);
fixed_string&
insert(
size_type index,
CharT const* s)
{
return insert(index, s, Traits::length(s));
}
fixed_string&
insert(
size_type index,
CharT const* s,
size_type count);
template<std::size_t M>
fixed_string&
insert(
size_type index,
fixed_string<M, CharT, Traits> const& s)
{
return insert(index, s.data(), s.size());
}
template<std::size_t M>
fixed_string&
insert(
size_type index,
fixed_string<M, CharT, Traits> const& s,
size_type index_str,
size_type count = npos);
iterator
insert(
const_iterator pos,
CharT ch)
{
return insert(pos, 1, ch);
}
iterator
insert(
const_iterator pos,
size_type count, CharT ch);
template<class InputIt>
#if GENERATING_DOCUMENTATION
iterator
#else
typename std::enable_if<
detail::is_input_iterator<InputIt>::value,
iterator>::type
#endif
insert(
const_iterator pos,
InputIt first,
InputIt last);
iterator
insert(
const_iterator pos,
std::initializer_list<CharT> init)
{
return insert(pos, init.begin(), init.end());
}
fixed_string&
insert(
size_type index,
string_view_type s)
{
return insert(index, s.data(), s.size());
}
template<class T>
#if GENERATING_DOCUMENTATION
fixed_string&
#else
typename std::enable_if<
std::is_convertible<T const&, string_view_type>::value &&
! std::is_convertible<T const&, CharT const*>::value,
fixed_string&>::type
#endif
insert(
size_type index,
T const& t,
size_type index_str,
size_type count = npos);
fixed_string&
erase(
size_type index = 0,
size_type count = npos);
iterator
erase(
const_iterator pos);
iterator
erase(
const_iterator first,
const_iterator last);
void
push_back(
CharT ch);
void
pop_back()
{
Traits::assign(s_[--n_], 0);
}
fixed_string&
append(
size_type count,
CharT ch)
{
insert(end(), count, ch);
return *this;
}
template<std::size_t M>
fixed_string&
append(
fixed_string<M, CharT, Traits> const& s)
{
insert(size(), s);
return *this;
}
template<std::size_t M>
fixed_string&
append(
fixed_string<M, CharT, Traits> const& s,
size_type pos,
size_type count = npos);
fixed_string&
append(
CharT const* s,
size_type count)
{
insert(size(), s, count);
return *this;
}
fixed_string&
append(
CharT const* s)
{
insert(size(), s);
return *this;
}
template<class InputIt>
#if GENERATING_DOCUMENTATION
fixed_string&
#else
typename std::enable_if<
detail::is_input_iterator<InputIt>::value,
fixed_string&>::type
#endif
append(
InputIt first,
InputIt last)
{
insert(end(), first, last);
return *this;
}
fixed_string&
append(
std::initializer_list<CharT> init)
{
insert(end(), init);
return *this;
}
fixed_string&
append(
string_view_type sv)
{
insert(size(), sv);
return *this;
}
template<class T>
#if GENERATING_DOCUMENTATION
fixed_string&
#else
typename std::enable_if<
std::is_convertible<T const&, string_view_type>::value &&
! std::is_convertible<T const&, CharT const*>::value,
fixed_string&>::type
#endif
append(
T const& t,
size_type pos,
size_type count = npos)
{
insert(size(), t, pos, count);
return *this;
}
template<std::size_t M>
fixed_string&
operator+=(
fixed_string<M, CharT, Traits> const& s)
{
return append(s.data(), s.size());
}
fixed_string&
operator+=(
CharT ch)
{
push_back(ch);
return *this;
}
fixed_string&
operator+=(
CharT const* s)
{
return append(s);
}
fixed_string&
operator+=(
std::initializer_list<CharT> init)
{
return append(init);
}
fixed_string&
operator+=(
string_view_type const& s)
{
return append(s);
}
template<std::size_t M>
int
compare(
fixed_string<M, CharT, Traits> const& s) const
{
return detail::lexicographical_compare<CharT, Traits>(
&s_[0], n_, &s.s_[0], s.n_);
}
template<std::size_t M>
int
compare(
size_type pos1,
size_type count1,
fixed_string<M, CharT, Traits> const& s) const
{
return detail::lexicographical_compare<CharT, Traits>(
substr(pos1, count1), s.data(), s.size());
}
template<std::size_t M>
int
compare(
size_type pos1,
size_type count1,
fixed_string<M, CharT, Traits> const& s,
size_type pos2,
size_type count2 = npos) const
{
return detail::lexicographical_compare(
substr(pos1, count1), s.substr(pos2, count2));
}
int
compare(
CharT const* s) const
{
return detail::lexicographical_compare<CharT, Traits>(
&s_[0], n_, s, Traits::length(s));
}
int
compare(
size_type pos1,
size_type count1,
CharT const* s) const
{
return detail::lexicographical_compare<CharT, Traits>(
substr(pos1, count1), s, Traits::length(s));
}
int
compare(
size_type pos1,
size_type count1,
CharT const*s,
size_type count2) const
{
return detail::lexicographical_compare<CharT, Traits>(
substr(pos1, count1), s, count2);
}
int
compare(
string_view_type s) const
{
return detail::lexicographical_compare<CharT, Traits>(
&s_[0], n_, s.data(), s.size());
}
int
compare(
size_type pos1,
size_type count1,
string_view_type s) const
{
return detail::lexicographical_compare<CharT, Traits>(
substr(pos1, count1), s);
}
template<class T>
#if GENERATING_DOCUMENTATION
int
#else
typename std::enable_if<
std::is_convertible<T const&, string_view_type>::value &&
! std::is_convertible<T const&, CharT const*>::value,
int>::type
#endif
compare(
size_type pos1,
size_type count1,
T const& t,
size_type pos2,
size_type count2 = npos) const
{
return compare(pos1, count1,
string_view_type(t).substr(pos2, count2));
}
string_view_type
substr(
size_type pos = 0,
size_type count = npos) const;
/// Copy a substring (pos, pos+count) to character string pointed to by `dest`.
size_type
copy(
CharT* dest,
size_type count,
size_type pos = 0) const;
/** Changes the number of characters stored.
If the resulting string is larger, the new
characters are uninitialized.
*/
void
resize(
std::size_t n);
/** Changes the number of characters stored.
If the resulting string is larger, the new
characters are initialized to the value of `c`.
*/
void
resize(
std::size_t n,
CharT c);
/// Exchange the contents of this string with another.
void
swap(
fixed_string& s);
/// Exchange the contents of this string with another.
template<std::size_t M>
void
swap(
fixed_string<M, CharT, Traits>& s);
//--------------------------------------------------------------------------
//
// Search
//
//--------------------------------------------------------------------------
private:
fixed_string&
assign_char(CharT ch, std::true_type);
fixed_string&
assign_char(CharT ch, std::false_type);
};
//------------------------------------------------------------------------------
//
// Disallowed operations
//
//------------------------------------------------------------------------------
// These operations are explicitly deleted since
// there is no reasonable implementation possible.
template<std::size_t N, std::size_t M, typename CharT, typename Traits>
void
operator+(
fixed_string<N, CharT, Traits>const& lhs,
fixed_string<M, CharT, Traits>const& rhs) = delete;
template<std::size_t N, typename CharT, typename Traits>
void
operator+(
CharT const* lhs,
fixed_string<N, CharT, Traits>const& rhs) = delete;
template<std::size_t N, typename CharT, typename Traits>
void
operator+(
CharT lhs,
fixed_string<N, CharT, Traits> const& rhs) = delete;
template<std::size_t N, typename CharT, typename Traits>
void
operator+(
fixed_string<N, CharT, Traits> const& lhs,
CharT const* rhs) = delete;
template<std::size_t N, typename CharT, typename Traits>
void
operator+(
fixed_string<N, CharT, Traits> const& lhs,
CharT rhs) = delete;
//------------------------------------------------------------------------------
//
// Non-member functions
//
//------------------------------------------------------------------------------
template<
std::size_t N, std::size_t M,
typename CharT, typename Traits>
bool
operator==(
fixed_string<N, CharT, Traits> const& lhs,
fixed_string<M, CharT, Traits> const& rhs)
{
return lhs.compare(rhs) == 0;
}
template<
std::size_t N, std::size_t M,
typename CharT, typename Traits>
bool
operator!=(
fixed_string<N, CharT, Traits> const& lhs,
fixed_string<M, CharT, Traits> const& rhs)
{
return lhs.compare(rhs) != 0;
}
template<
std::size_t N, std::size_t M,
typename CharT, typename Traits>
bool
operator<(
fixed_string<N, CharT, Traits> const& lhs,
fixed_string<M, CharT, Traits> const& rhs)
{
return lhs.compare(rhs) < 0;
}
template<
std::size_t N, std::size_t M,
typename CharT, typename Traits>
bool
operator<=(
fixed_string<N, CharT, Traits> const& lhs,
fixed_string<M, CharT, Traits> const& rhs)
{
return lhs.compare(rhs) <= 0;
}
template<
std::size_t N, std::size_t M,
typename CharT, typename Traits>
bool
operator>(
fixed_string<N, CharT, Traits> const& lhs,
fixed_string<M, CharT, Traits> const& rhs)
{
return lhs.compare(rhs) > 0;
}
template<
std::size_t N, std::size_t M,
typename CharT, typename Traits>
bool
operator>=(
fixed_string<N, CharT, Traits> const& lhs,
fixed_string<M, CharT, Traits> const& rhs)
{
return lhs.compare(rhs) >= 0;
}
template<std::size_t N, typename CharT, typename Traits>
bool
operator==(
CharT const* lhs,
fixed_string<N, CharT, Traits> const& rhs)
{
return detail::lexicographical_compare<CharT, Traits>(
lhs, Traits::length(lhs),
rhs.data(), rhs.size()) == 0;
}
template<std::size_t N, typename CharT, typename Traits>
bool
operator==(
fixed_string<N, CharT, Traits> const& lhs,
CharT const* rhs)
{
return detail::lexicographical_compare<CharT, Traits>(
lhs.data(), lhs.size(),
rhs, Traits::length(rhs)) == 0;
}
template<std::size_t N, typename CharT, typename Traits>
bool
operator!=(
CharT const* lhs,
fixed_string<N, CharT, Traits> const& rhs)
{
return detail::lexicographical_compare<CharT, Traits>(
lhs, Traits::length(lhs),
rhs.data(), rhs.size()) != 0;
}
template<std::size_t N, typename CharT, typename Traits>
bool
operator!=(
fixed_string<N, CharT, Traits> const& lhs,
CharT const* rhs)
{
return detail::lexicographical_compare<CharT, Traits>(
lhs.data(), lhs.size(),
rhs, Traits::length(rhs)) != 0;
}
template<std::size_t N, typename CharT, typename Traits>
bool
operator<(
CharT const* lhs,
fixed_string<N, CharT, Traits> const& rhs)
{
return detail::lexicographical_compare<CharT, Traits>(
lhs, Traits::length(lhs),
rhs.data(), rhs.size()) < 0;
}
template<std::size_t N, typename CharT, typename Traits>
bool
operator<(
fixed_string<N, CharT, Traits> const& lhs,
CharT const* rhs)
{
return detail::lexicographical_compare<CharT, Traits>(
lhs.data(), lhs.size(),
rhs, Traits::length(rhs)) < 0;
}
template<std::size_t N, typename CharT, typename Traits>
bool
operator<=(
CharT const* lhs,
fixed_string<N, CharT, Traits> const& rhs)
{
return detail::lexicographical_compare<CharT, Traits>(
lhs, Traits::length(lhs),
rhs.data(), rhs.size()) <= 0;
}
template<std::size_t N, typename CharT, typename Traits>
bool
operator<=(
fixed_string<N, CharT, Traits> const& lhs,
CharT const* rhs)
{
return detail::lexicographical_compare<CharT, Traits>(
lhs.data(), lhs.size(),
rhs, Traits::length(rhs)) <= 0;
}
template<std::size_t N, typename CharT, typename Traits>
bool
operator>(
CharT const* lhs,
fixed_string<N, CharT, Traits> const& rhs)
{
return detail::lexicographical_compare<CharT, Traits>(
lhs, Traits::length(lhs),
rhs.data(), rhs.size()) > 0;
}
template<std::size_t N, typename CharT, typename Traits>
bool
operator>(
fixed_string<N, CharT, Traits> const& lhs,
CharT const* rhs)
{
return detail::lexicographical_compare<CharT, Traits>(
lhs.data(), lhs.size(),
rhs, Traits::length(rhs)) > 0;
}
template<std::size_t N, typename CharT, typename Traits>
bool
operator>=(
CharT const* lhs,
fixed_string<N, CharT, Traits> const& rhs)
{
return detail::lexicographical_compare<CharT, Traits>(
lhs, Traits::length(lhs),
rhs.data(), rhs.size()) >= 0;
}
template<std::size_t N, typename CharT, typename Traits>
bool
operator>=(
fixed_string<N, CharT, Traits> const& lhs,
CharT const* rhs)
{
return detail::lexicographical_compare<CharT, Traits>(
lhs.data(), lhs.size(),
rhs, Traits::length(rhs)) >= 0;
}
//------------------------------------------------------------------------------
//
// swap
//
//------------------------------------------------------------------------------
template<std::size_t N, typename CharT, typename Traits>
void
swap(
fixed_string<N, CharT, Traits>& lhs,
fixed_string<N, CharT, Traits>& rhs)
{
lhs.swap(rhs);
}
template<
std::size_t N, std::size_t M,
typename CharT, typename Traits>
void
swap(
fixed_string<N, CharT, Traits>& lhs,
fixed_string<M, CharT, Traits>& rhs)
{
lhs.swap(rhs);
}
//------------------------------------------------------------------------------
//
// Input/Output
//
//------------------------------------------------------------------------------
template<std::size_t N, typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
fixed_string<N, CharT, Traits> const& s)
{
return os << static_cast<
basic_string_view<CharT, Traits>>(s);
}
//------------------------------------------------------------------------------
//
// Numeric conversions
//
//------------------------------------------------------------------------------
/** Returns a static string representing an integer as a decimal.
@param x The signed or unsigned integer to convert.
This must be an integral type.
@return A @ref fixed_string with an implementation defined
maximum size at least as large enough to hold the longest
possible decimal representation of any integer of the given type.
*/
template<
class Integer
#ifndef GENERATING_DOCUMENTATION
, class = typename std::enable_if<
std::is_integral<Integer>::value>::type
#endif
>
fixed_string<detail::max_digits(sizeof(Integer))>
to_fixed_string(Integer x);
} // fixed_string
} // boost
#include <boost/fixed_string/impl/fixed_string.hpp>
#endif