initial commit
This commit is contained in:
commit
75799f4652
9 changed files with 316 additions and 0 deletions
30
include/xo/stringliteral/string_view_concat.hpp
Normal file
30
include/xo/stringliteral/string_view_concat.hpp
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#include <string_view>
|
||||
#include <array>
|
||||
|
||||
template <std::string_view const & ... Strings>
|
||||
struct sv_concat
|
||||
{
|
||||
static constexpr auto impl() noexcept {
|
||||
constexpr std::size_t n = (Strings.size() + ... + 0);
|
||||
|
||||
std::array<char, n + 1> arr{};
|
||||
|
||||
auto append = [i=0, &arr](const auto & s) mutable {
|
||||
for (auto c : s)
|
||||
arr[i++] = c;
|
||||
};
|
||||
(append(Strings), ...);
|
||||
arr[n] = '\0';
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
static constexpr auto arr = impl();
|
||||
static constexpr std::string_view value {
|
||||
arr.data(),
|
||||
arr.size() - 1
|
||||
};
|
||||
};
|
||||
|
||||
template <std::string_view const & ... Strings>
|
||||
static constexpr auto concat_v = sv_concat<Strings...>::value;
|
||||
96
include/xo/stringliteral/stringliteral.hpp
Normal file
96
include/xo/stringliteral/stringliteral.hpp
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/** @file stringliteral.hpp
|
||||
*
|
||||
* Author: Roland Conybeare
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
/** @class stringliteral
|
||||
*
|
||||
* @brief class to represent a literal string at compile time, for use as template argument
|
||||
**/
|
||||
template <std::size_t N>
|
||||
struct stringliteral {
|
||||
constexpr stringliteral() { if (N > 0) value_[0] = '\0'; }
|
||||
constexpr stringliteral(const char (&str)[N]) { std::copy_n(str, N, value_); }
|
||||
constexpr int size() const { return N; }
|
||||
|
||||
constexpr char const * c_str() const { return value_; }
|
||||
|
||||
char value_[N];
|
||||
};
|
||||
|
||||
/** @brief all_same_v<T1, .., Tn> is true iff types T1 = .. = Tn
|
||||
**/
|
||||
template < typename First, typename... Rest >
|
||||
constexpr auto
|
||||
all_same_v = std::conjunction_v< std::is_same<First, Rest>... >;
|
||||
|
||||
/** @brief concatenate string literals
|
||||
*
|
||||
* NOTE: this isn't constexpr in clang16
|
||||
**/
|
||||
template < typename... Ts>
|
||||
constexpr auto
|
||||
stringliteral_concat(Ts && ... args)
|
||||
{
|
||||
#ifdef NOT_USING
|
||||
static_assert(all_same_v<std::decay_t<Ts>...>,
|
||||
"string must share the same char type");
|
||||
|
||||
using char_type = std::remove_const_t< std::remove_pointer_t < std::common_type_t < Ts... > > >;
|
||||
#endif
|
||||
using char_type = char;
|
||||
|
||||
/** n1: total number of bytes used by arguments **/
|
||||
constexpr size_t n1 = (sizeof(Ts) + ...);
|
||||
/** z1: each string arg has a null terminator included in its size,
|
||||
* z1 is the number of arguments in parameter pack Ts,
|
||||
* which equals the number of null terminators used
|
||||
**/
|
||||
constexpr size_t z1 = sizeof...(Ts);
|
||||
|
||||
/** n: number of chars in concatenated string. +1 for final null **/
|
||||
constexpr size_t n
|
||||
= (n1 / sizeof(char_type)) - z1 + 1;
|
||||
|
||||
stringliteral<n> result;
|
||||
size_t pos = 0;
|
||||
|
||||
auto detail_concat = [ &pos, &result ](auto && arg) {
|
||||
constexpr auto count = (sizeof(arg) - sizeof(char_type)) / sizeof(char_type);
|
||||
|
||||
std::copy_n(arg.c_str(), count, result.value_ + pos);
|
||||
pos += count;
|
||||
};
|
||||
|
||||
(detail_concat(args), ...);
|
||||
|
||||
//return stringliteral("");
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef NOT_USING
|
||||
template <std::size_t N1, std::size_t N2>
|
||||
constexpr auto
|
||||
stringliteral_compare(stringliteral<N1> && s1, stringliteral<N2> && s2)
|
||||
{
|
||||
return std::string_view(s1.value_) <=> std::string_view(s2.value_);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <std::size_t N1, std::size_t N2>
|
||||
constexpr auto
|
||||
stringliteral_compare(const stringliteral<N1> & s1, const stringliteral<N2> & s2)
|
||||
{
|
||||
return std::string_view(s1.value_) <=> std::string_view(s2.value_);
|
||||
}
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/** end stringliteral.hpp **/
|
||||
36
include/xo/stringliteral/stringliteral_iostream.hpp
Normal file
36
include/xo/stringliteral/stringliteral_iostream.hpp
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/** @file stringliteral_iostream.hpp
|
||||
*
|
||||
* Author: Roland Conybeare
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stringliteral.hpp"
|
||||
#include <ostream>
|
||||
//#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
/** @brief print stringliteral on stream os.
|
||||
*
|
||||
**/
|
||||
template <std::size_t N>
|
||||
void
|
||||
print_stringliteral (std::ostream & os, const stringliteral<N> & x) {
|
||||
os << x.c_str();
|
||||
}
|
||||
|
||||
/** @brief print stringliteral x on stream os.
|
||||
*
|
||||
* Example
|
||||
* @code
|
||||
* cout << stringliteral("foo"); // outputs "foo"
|
||||
**/
|
||||
template <std::size_t N>
|
||||
inline std::ostream &
|
||||
operator<< (std::ostream & os, const stringliteral<N> & x) {
|
||||
print_stringliteral(os, x);
|
||||
return os;
|
||||
}
|
||||
} /*namespace xo*/
|
||||
|
||||
/** end stringliteral_iostream.hpp **/
|
||||
Loading…
Add table
Add a link
Reference in a new issue