Reputation: 107
So, I'm attempting to mess with constexpr
strings as one will do and really only have this thus far:
template<char... CS> struct text {
static constexpr char c_str[] = {CS...};
static constexpr int size = sizeof...(CS);
};
and so this compiles
text<'a','b','c'> t;
std::cout<< t.c_str <<std::endl;
and outputs 'abc'
as expected.
What I'm wondering is if there's a non-convoluted way to do the reverse; have a function that returns a text type with the necessary char
template arguments given a char
array.
Upvotes: 3
Views: 142
Reputation: 66230
Not exactly what you asked... and a little convoluted, I suppose... but if you define a constexpr
function to detect the length of a string
constexpr std::size_t strLen (char const * str, std::size_t len = 0U)
{ return *str ? strLen(++str, ++len) : len; }
and an helper struct that define the required type
template <char const *, typename>
struct foo_helper;
template <char const * Str, std::size_t ... Is>
struct foo_helper<Str, std::index_sequence<Is...>>
{ using type = text<Str[Is]...>; };
you can obtain your type passing the string to
template <char const * Str>
struct foo : public foo_helper<Str, std::make_index_sequence<strLen(Str)>>
{ };
Unfortunately you can't pass a string literal to it in this way
foo<"abc">::type
but you have to pass from a global variable
constexpr char abcVar[] = "abc";
and call foo
using the global variable
foo<abcVar>::type
This solution uses std::index_sequence
and std::make_index_sequence
, available only starting from C++14, but isn't too difficult to write a substitute for they in C++11.
The following is a full working example
#include <utility>
#include <iostream>
#include <type_traits>
template <char ... CS>
struct text
{
static constexpr char c_str[] = {CS...};
static constexpr int size = sizeof...(CS);
};
constexpr std::size_t strLen (char const * str, std::size_t len = 0U)
{ return *str ? strLen(++str, ++len) : len; }
template <char const *, typename>
struct foo_helper;
template <char const * Str, std::size_t ... Is>
struct foo_helper<Str, std::index_sequence<Is...>>
{ using type = text<Str[Is]...>; };
template <char const * Str>
struct foo : public foo_helper<Str, std::make_index_sequence<strLen(Str)>>
{ };
constexpr char abcVar[] = "abc";
int main()
{
static_assert(std::is_same<foo<abcVar>::type,
text<'a', 'b', 'c'>>{}, "!");
}
Off Topic: I suggest to add an ending zero in c_str[]
static constexpr char c_str[] = {CS..., 0};
if you want use it as the c_str()
method of std::string
.
Upvotes: 2