Say I have
constexpr const std::uint8_t major = 1;
constexpr const std::uint8_t minor = 10;
constexpr const std::uint8_t bugfix = 0;
and I want
constexpr const char* version_string(){ ... }
to return the equivalent of "1.10.0"
in this example, how would I do it?
I assume I'll need both of these, in constexpr
:
The problem is purely academic, and I see little to no use to actually have it constexpr
other than "it's possible". I just can't see how this would pan out. I'm willing to accept C++1y solutions that work on GCC 4.9 and Clang 3.4/3.5.
I believe I have found nearly what I seek on some Japanese blogs:
I will see what I can do with these, and perhaps answer this self-declared interesting question myself when I'm satisfied with the result.
Here is a C++11 solution. It uses class templates with char...
parameter pack to simulate strings:
#include <iostream>
#include <type_traits>
template <char... symbols>
struct String
{
static constexpr char value[] = {symbols...};
};
template <char... symbols>
constexpr char String<symbols...>::value[];
template <typename, typename>
struct Concat;
template <char... symbols1, char... symbols2>
struct Concat<String<symbols1...>, String<symbols2...>>
{
using type = String<symbols1..., symbols2...>;
};
template <typename...>
struct Concatenate;
template <typename S, typename... Strings>
struct Concatenate<S, Strings...>
{
using type = typename Concat<S, typename Concatenate<Strings...>::type>::type;
};
template <>
struct Concatenate<>
{
using type = String<>;
};
template <std::size_t N>
struct NumberToString
{
using type = typename Concat
<
typename std::conditional<(N >= 10), typename NumberToString<N / 10>::type, String<>>::type,
String<'0' + N % 10>
>::type;
};
template <>
struct NumberToString<0>
{
using type = String<'0'>;
};
constexpr const std::uint8_t major = 1;
constexpr const std::uint8_t minor = 10;
constexpr const std::uint8_t bugfix = 0;
using VersionString = Concatenate
<
NumberToString<major>::type,
String<'.'>,
NumberToString<minor>::type,
String<'.'>,
NumberToString<bugfix>::type
>::type;
constexpr const char* version_string = VersionString::value;
int main()
{
std::cout << version_string << std::endl;
}
See live example.