Related
We have a formatting library similar to fmtlib which allows us to format strings like this:
int foo = 1;
double bar = 2.3;
FMT("foo={} bar={}", foo, bar);
We recently added parsing of the format string at compile time, allowing us to specify, eg width,
precision etc directly in the format string
// print foo with width=5, pad with 0; print bar with width 6, precision 2
// as decimal floating point
FMT("foo={:05} bar={:6.2f}", foo, bar);
The way we do this is as follows:
We have a struct which I can use to pass the format string as a template parameter
struct FmtString
{
template<std::size_t N>
constexpr FmtString(const char (&s)[N])
: str(s)
{}
const char* const str;
};
Together with this FmtString and the arguments to be formatted, we use the following somewhat convoluted dance
to generate a std::tuple of FmtSpecT format specifications.
We use the variadic template parameter pack to generate a std::index_sequence:
// use Ts... to create a tuple of the argument types and an std::index_sequence
template<FmtString S, typename... Ts>
struct CompiledFmtSpec
{
using type = decltype(compileFmtSpec<S, std::tuple<Ts...>>(std::index_sequence_for<Ts...> {}));
};
// pull the indices out of the std::index_sequence
template<FmtString S, typename Tuple, std::size_t... Is>
consteval auto compileFmtSpec(std::index_sequence<Is...>)
{
return typename FmtSpecs<S, Tuple, Is...>::type {};
}
We use the std::index_sequence to generate a variadic std::size_t sequence which we can use to
extract each argument from the tuple of arguments, and its respective sequence value
template<FmtString S, typename Tuple, std::size_t... Is>
struct FmtSpecs
{
using type = std::tuple<FmtSpecWrapper<S, std::tuple_element_t<Is, Tuple>, Is>...>;
};
This results in the following tuple:
std::tuple<
FmtSpecWrapper<S, T0, 0>,
FmtSpecWrapper<S, T1, 1>,
FmtSpecWrapper<S, T2, 2>,
...
FmtSpecWrapper<S, Tn, n>>
We can then specialise FmtSpecWrapper for the particular type and parse its supported format spec
Here is the default implementation
template<FmtString S, typename T, std::size_t I>
struct FmtSpecWrapper
{
using type = decltype(parseFmtString<S, I>());
};
template<FmtString S, std::size_t I>
consteval auto parseFmtString()
{
constexpr const char* pos = findFmtSpec(S, I);
constexpr FmtSpec fmt = parseFmtSpec(pos);
return FmtSpecT<fmt.pad, fmt.align_right, fmt.sign, fmt.width, fmt.precision, fmt.type, fmt.spec_len> {};
}
This results in a FmtSpecT specialisation, which has the following NTTPs:
template<char Pad, bool AlignRight, bool Sign, int Width, int Precision, char Type, int SpecLen>
struct FmtSpecT
{
static constexpr char pad = Pad;
static constexpr bool align_right = AlignRight;
static constexpr bool sign = Sign;
static constexpr int width = Width;
static constexpr int precision = Precision;
static constexpr char type = Type;
static constexpr int spec_len = SpecLen;
};
During formatting we can then pull out each FmtSpecT and use the members to format the argument.
The issue I'd like to try and solve is findFmtSpec(S, I).
Its job is to find the I'th format spec from the format string S.
constexpr const char* findFmtSpec(const FmtString& S, std::size_t i)
{
std::size_t curr = 0;
const char* next = S.str;
while (*next)
{
const char c = *next++;
if (c == '{')
{
if (c == *next) // found an escaped brace; {{ or }}
{
++next;
}
else // found the start of the fmt spec
{
if (curr == i)
return next;
++curr;
++next;
}
}
}
throw std::domain_error("too many arguments for format string");
}
My issue is that it is Big O N^2, as it starts from 0 for every argument.
Ideally I would be able to start from the end of the previous format spec and seek forwards to find the next, turning the complexity into O(N).
Any ideas on how I can modify findFmtSpec so that for each i it starts from the return value of the previouc call?
FmtString S is a template parameter, so it is usable in constant expressions.
Therefore all you need to do is write a constexpr function that extracts the specifiers up-front into a suitable container type, for example std::array<std::string_view, N>. You can either enforce directly in the function that the number of specifiers matches sizeof...(Ts), so that N can just be that, or you can write another constexpr function which first counts the number of arguments:
struct FmtString
{
template<std::size_t N>
constexpr FmtString(const char (&s)[N])
: str(s)
{}
const char* const str;
template<FmtString S>
static constexpr auto findFmtSpec = []{
constexpr auto N = []{
// iterate `S.str` here and return number of specifiers
}();
std::array<const char*, N> result;
// iterate `S.str` again and store beginning of format specifiers consecutively in `result`.
return result;
}();
};
Then parseFmtString can just use FmtString::findFmtSpec<S>[I]. I am using a static member variable template instead of a static function template to make sure that the compiler doesn't keep reevaluating an equivalent function call, although I think the compiler should memoize calls with the same arguments. I used nested lambdas for brevity, but you might want to put these into separate functions. There is also no particular reason to have the variable template be a member. It works outside the class as well.
You can also just generate the whole tuple this way:
template<FmtString S, typename... Ts>
static constexpr auto specs = []{
// number of specifiers, can be `sizeof...(Ts)`
// if no specific error handling is required
constexpr auto N = []{
// iterate `S.str` here and return number of specifiers
}();
if constexpr(sizeof...(Ts) != N) {
// handle argument number mismatch
} else {
// specs as values
constexpr auto specs = []{
std::array<FmtSpec, N> specs;
// iterate `S.str` again and store `FmtSpec` for each specifier consecutively in `specs`
return specs;
}();
// lift specs into type (template arguments)
return []<std::size_t... Is>(std::index_sequence<Is...>){
return std::tuple<FmtSpecWrapper<S, Ts, FmtSpecT<specs[Is].pad, /*...*/>>...>{};
}(std::make_index_sequence<N>{});
}
}();
I have a class with a template that accepts an integer:
template <unsigned int N>
class Example {};
I'm looking for a way to define a (member)function that accepts some amount of Example objects as arguments. The amount is to be determined by N, so the function would be used like this:
Function(Example<2>(), Example<2>());
Function(Example<3>(), Example<3>(), Example<3>());
What I tried so far:
Using an initializer list, one is able to pass a set of objects to the function:
template <unsigned int N>
void Function(std::initializer_list<Example<N>> list);
//...
Function({Example<2>(), Example<2>()});
However, the problem besides the fact that really only one argument is passed(the list), is that with this method any number of arguments can be used:
Function({Example<2>()});
I also tried using a variadic function:
template <unsigned int N>
void Function(Example<N> e...)
{
va_list args;
va_start(args, e);
//...
}
Function(Example<2>(), Example<2>());
This makes it possible to use real parameters, but the problem of using any number of arguments remains, and it's not possible to know how many arguments were actually passed.
Assuming you want the number of arguments to be deduced from the Example<N> type, and that all Example<I> should share the same such N, a C++17 solution might be
template <unsigned int... I>
auto Function( Example<I>... ) ->
std::enable_if_t<( ( I == sizeof...(I) ) && ... )>
{
// or static_assert() if you always want an error
}
Make Function a variadic template and use std::enable_if_t to constrain your it:
Some IsExample trait can be used to make sure that all arguments are instances of Example
sizeof...(pack) can be used to get the size of the parameter pack
template <unsigned int N, typename... Ts>
auto Function(Ts... xs)
-> std::enable_if_t<(IsExample<Ts>::value && ...)
&& (sizeof...(Ts) == N)>
{
}
live example on wandbox
You should utilize variadic function template with static_assert. Unlike approaches involving enable_if this one will produce a readable error message if incorrect arguments are passed.
template<unsigned int ... I>
void Function(Example<I>... items)
{
static_assert
(
true && (... && (static_cast<unsigned int>(sizeof...(I)) == I))
, "This function accepts N arguments of type Example<N>"
);
}
Online compiler
There are many answers that cover SFINAE friendly based constraints, but I don't like placing my SFINAE in the return value:
template <unsigned int... Is,
std::enable_if_t<( ( Is == sizeof...(Is) ) && ... ), bool> = true
>
void Function( Example<Is>... examples )
{
// code
}
or
template<bool b>
using test_requirement = std::enable_if_t<b, bool>;
template <unsigned int... Is,
test_requirement<( ( Is == sizeof...(Is) ) && ... )> = true
>
void Function( Example<Is>... examples )
{
// code
}
+1 for the Massimiliano Janes's elegant solution.
Unfortunately use folding so works only for C++17.
To test, with C++11/C++14, that all I are equals to sizeof...(I) (and maybe that sizeof...(I) is equal to N, where N is the class template argument), it's enough test that a variadic type, that receive unsigned values, is the same type with a different order of values.
I mean: declaring a trivial struct as
template <std::size_t ... Is>
struct IList;
the test can be
std::is_same<IList<N, sizeof...(Is), Is...>,
IList<sizeof...(Is), Is..., N>>::value
Starting from C++14 it's possible to use std::index_sequence instead of IList.
So Example can be written as
template <unsigned int N>
struct Example
{
template <unsigned int ... Is>
auto Function (Example<Is> ...)
-> typename std::enable_if<
std::is_same<IList<N, sizeof...(Is), Is...>,
IList<sizeof...(Is), Is..., N>>::value>::type
{ /* do something */ }
};
The following is a example of use (but remember to include <type_traits>)
int main()
{
Example<1U> e1;
Example<2U> e2;
// e1.Function(); // error
e1.Function(Example<1>{}); // compile
//e1.Function(Example<1>{}, Example<1>{}); // error
// e2.Function(); // error
//e2.Function(Example<2>{}); // error
e2.Function(Example<2>{}, Example<2>{}); // compile
//e2.Function(Example<2>{}, Example<2>{}, Example<2>{}); // error
}
Consider a compile-time function of the form:
template <unsigned int Value>
constexpr unsigned int function()
{
// Just for the example, but it could be very complicated here
return Value*Value;
}
How to write the runtime equivalent that will call the right compile-time version using template metaprogramming, knowing that the value will always be in the [From, To[ interval:
template <unsigned int From, unsigned int To, /* Something here */>
constexpr unsigned int function(const unsigned int value)
{
// Something here
}
The branching to the right version should be as fast as possible.
For example function<0, 32>(6) (runtime version) should call function<6>() (compile-time version).
EDIT: Explanation:
Why do I want to do this? This function (real use case) need to be as fast as possible (supercomputing issues). By providing the parameter at compile-time, I can generate very efficient code. If I simply move the value from the template parameter to a function parameter, the code is between 10 and 100 times slower. But in fact, this parameter does not have a very wide range of possible values (like between 0 and 32): so it would be far more efficient to branch at runtime on the right compile-time version.
The easiest way is to set up a recursive cascading if/recurse chain.
#define RETURNS(X) -> decltype(X) { return (X); }
template<unsigned From, unsigned To, typename Target>
struct CallIf {
constexpr auto operator()( unsigned N )
RETURNS( (N==From)?Target::template func<From>():CallIf<From+1, To, Target>()( N ) );
};
template<unsigned From, typename Target>
struct CallIf<From, From+1, Target> {
constexpr auto operator()( unsigned N )
RETURNS( Target::template func<From>() );
};
struct Func {
template<unsigned V>
constexpr unsigned func() const {
return function<V>();
}
};
or something like that, and rely on the compiler collapsing that chain of ifs down to one. (if you know the return type, you can do away with that annoying RETURNS macro, or if you have C++1y features you can do the same).
Now, you might want to compare this to a version that does a binary search on value in that range, using a similar recursive call case. Similarly, you could do it by checking and setting bits in a compile time value.
template<unsigned From, unsigned To, typename Target>
struct CallIf {
enum { Mid = From + (To-From)/2 }; // avoid overflow risk
constexpr auto operator()( unsigned N )
RETURNS( (N>=Mid)?CallIf<Mid, To, Target>()(N):CallIf<From,Mid,Target>()(N) );
};
with the same specialization for the 1-width case.
Another approach would be to set up a static array of invocations of function<V> and then do an array dereference at run time:
template<unsigned...> struct indexes {};
template<unsigned Min, unsigned Max, unsigned... Is> struct make_indexes:make_indexes<Min, Max-1, Max-1, Is...> {};
template<unsigned Min, unsigned... Is> struct make_indexes<Min, Min, Is...>:indexes<Is...> {};
template<unsigned From, unsigned To, typename Target>
struct CallIf {
template<unsigned... Is>
unsigned Invoke( indexes<Is...>, unsigned N ) const {
typedef unsigned(*target)();
static target ts[] = { &(function<Is>)... };
return ts[N-From]();
};
unsigned operator()( unsigned N ) const {
return Invoke( make_indexes<From, To>(), N );
}
};
although I'm not sure how to make the above constexpr easily in C++11 at least, and I skipped out on doing return-type deduction.
None of the above are tested or compiled, so most likely will require some repair. But the core concept will work. The specialization might need some work: doing <From, From+1 to terminate is something I haven't done in practice: if that causes issues, you can do <From, Width based helper, and specialize on Width=1.
I personally call this technique (embodied in the CallIf type above) the "magic switch", where we take a run time valid and "magically" make it a compile time value. I only mention this because you can probably find me talking about it on stack overflow by googling Yakk and "magic switch" (and site:stackoverflow.com) for other variations, some of which have been compiled and have live examples attached.
Finally, while the last version (the manual jump table) may be fastest, if you are calling it so often that the speed of this invocation is key, you might want to think about wrapping not just the call site, but the algorithm surrounding it in a magic switch: do the dispatching earlier. If, however, you only get the index at the last moment, and you are ok with a non-constexpr call, it should work. Note that static arrays will be created for each Function and To and From used.
You may create an (constexpr) array of results, something like :
#if 1 // Not in C++11
template <std::size_t ...> struct index_sequence {};
template <std::size_t I, std::size_t ...Is>
struct make_index_sequence : make_index_sequence < I - 1, I - 1, Is... > {};
template <std::size_t ... Is>
struct make_index_sequence<0, Is...> : index_sequence<Is...> {};
#endif
template <unsigned int Value>
constexpr unsigned int function()
{
// Just for the example, but it could be very complicated here
return Value * Value;
}
namespace detail
{
template <std::size_t From, std::size_t...Is>
struct result_array
{
static constexpr std::array<unsigned int, sizeof...(Is)> values = {{::function<From + Is>()...}};
};
template <std::size_t From, std::size_t...Is>
constexpr std::array<unsigned int, sizeof...(Is)> result_array<From, Is...>::values;
template <std::size_t From, std::size_t...Is>
constexpr unsigned int function(unsigned int value, index_sequence<Is...>)
{
return result_array<From, Is...>::values[value - From];
}
} // namespace detail
template <unsigned int From, unsigned int To>
constexpr unsigned int function(const unsigned int value)
{
static_assert(From < To, "Invalid template parameters");
return detail::function<From>(value, make_index_sequence<std::size_t(To + 1 - From)>());
}
Background
C++11 initializer lists can be used to initialize vectors and arrays with argument passing to constructors.
I have a piece of code below where I would like to initialize such an array with all the enumerations of eCOLORS from eCOLORS::First to eCOLORS::Last using initializer lists.
Original Code
Since all information is known at compile time, I think there is a way to solve this problem.
enum class eCOLORS
{
kBLUE=0, kGREEN, kRED, kPURPLE,
First=kBLUE, Last=kPURPLE
};
template< typename E >
size_t Size()
{
return (size_t)(E::Last) - (size_t)(E::First) + 1;
}
struct Foo
{
Foo( eCOLORS color ) { }
};
int main(int argc, char** argv)
{
Foo a[2] = {
{ eCOLORS::kRED },
{ eCOLORS::kGREEN }
}; // works, but requires manual maintenance if I add another color
/* how to feed v with all the enums from First to Last
without hard-coding?
Foo v[Size<eCOLORS>()] = {
};
*/
}
Ugly Pseudo-Answer
The consensus appears to be that there is currently no way to this.
My original intent in asking this question is, I want to automagically
create an array of Foo objects whose initialization is solely based on
the enumeration of eColors. I wanted a no maintenance solution that
would work even after you add more entries into eColors.
Using the Enum class from this earlier post, I can write a function template that gives me the functionality that I need. Even without using that Enum class, you could still loop from eCOLORS::First to eCOLORS::Last, along with some ugly casts.
My ugly pseudo-answer is kludgy (nowhere as nice as a compile-time initializer list), but at least it is zero maintenance.
NOTE: if better solutions come up, I will update the OP accordingly.
template <typename T, typename E>
std::vector< T >
Initialize_With_Enums()
{
std::vector< T > v;
for( auto p : Enum<E>() )
v.push_back( T( p ));
return v;
}
int main( int argc, char** argv )
{
auto w = Initialize_With_Enum<Foo,eCOLORS>();
}
You can do this with variadic templates and what I'm going to call the "indices trick".
typedef std::underlying_type<eCOLORS>::type underlying;
// just a type to carry around variadic pack of numbers
template <underlying...> struct indices {};
// A template to build up a pack of Count numbers from first
// third parameter is an accumulator
template <underlying First, underlying Count, typename Acc = indices<>>
struct make_indices;
// base case
template <underlying X, underlying... Acc>
struct make_indices<X, 0, indices<Acc...>> { typedef indices<Acc...> type; };
// recursive build up of the pack
template <underlying First, underlying Count, underlying... Acc>
struct make_indices<First, Count, indices<Acc...>>
: make_indices<First, Count-1, indices<First+Count-1, Acc...>> {};
size_t const max_colors = underlying(eCOLORS::Last) - underlying(eCOLORS::First)+1;
// shortcut
typedef make_indices<
underlying(eCOLORS::First),
max_colors
>::type all_eCOLORS_indices;
// takes a dummy parameter with the pack we built
template <underlying... Indices>
std::array<eCOLORS, max_colors> const& all_colors(indices<Indices...>) {
// convert each number to the enum and stick it in an static array
static std::array<eCOLORS, max_colors> const all = {
eCOLORS(Indices)...
};
return all;
}
std::array<eCOLORS, max_colors> const& all_colors() {
// create a dummy object of the indices pack type and pass it
return all_colors(all_eCOLORS_indices());
}
This assumes all the enumerators are sequential, and needs std::underlying_type which is not supported in GCC 4.6 (will be in 4.7, but you can emulate it to a certain extent).
I don't think you can do this with initializer lists. This isn't the sort of thing they're meant for. I think you could manage a decent workaround by defining an iterator that would iterate over any enumeration that had a First and Last member.
But first, your definition of Size isn't quite right...
template< typename E >
constexpr size_t Size()
{
return (size_t)(E::Last) - (size_t)(E::First) + 1;
}
Declaring it constexpr means that it's definition is a compile time constant. So you can use it in template arguments and the like.
I don't have time right now to create the range class for you. It's somewhat complicated by the fact that enum values and integers are not interchangeable for enum classes. But it's not too hard. You might use this question "Is there a range class in C++0x (aka C++11) for use with range based for loops?" as a starting point. You basically use the vector initializer that initializes from a [begin, end) pair in conjuction with a range class like is discussed in that question.
There isn't an automatic way to do this using initializer lists, but you could do it algorithmically if you know the first and last values of the enum by just using a for loop to insert the values.
The MACRO solution.
#include <stdio.h>
#include <initializer_list>
#define COLORS(V,E) \
V(RED) \
V(GREEN) \
E(BLUE)
#define COMMA(V) \
V,
#define NCOMMA(V) \
V
#define SCOMMA(V) \
#V,
#define SNCOMMA(E) \
#E
enum Colors {
COLORS(COMMA,NCOMMA)
};
const char * colors[] = {
COLORS(SCOMMA,SNCOMMA)
};
#define INIT_LIST(V) \
{ V(COMMA,NCOMMA) }
int main(int argc, char **argv) {
for ( auto i : INIT_LIST(COLORS) ) {
printf("%s\n", colors[i]);
}
}
I like your problem. Long ago, this kind of thing used to be handled with X macros http://www.drdobbs.com/the-new-c-x-macros/184401387
I'm a c++11 newb, but after some fiddling around I've got some kind of solution (g++ 4.8.4):
enum class Symbols { FOO, BAR, BAZ, First=FOO, Last=BAZ };
I kept your Size() but added some other boilerplate to make the initialization, lower down, easier to read.
template< typename E > constexpr size_t Size() { return (size_t)(E::Last) - (size_t)(E::First) + 1; }
template< typename E > constexpr size_t as_sizet( E s ) { return (size_t)s; }
template< typename E > constexpr E operator++( E& s, int ) { return (E)(1 + (size_t)s); }
template< typename E > constexpr bool operator<=( E& a, E& b ) { return (size_t)a < (size_t)b; }
There are two bits of magic here:
We return a reference to the initialized array (itself another template parameter)
We initialize a static array during the recursive call using a junk argument
Like so:
template< typename E, typename EARR >
constexpr EARR& init_array( EARR& zArr, E sym = E::First, E junk = E::Last )
{
return sym <= E::Last ? init_array( zArr, sym++, zArr[ as_sizet( sym ) ] = sym ) : zArr;
}
In the end, it comes together with:
The typedef
The static declaration of the array
The reference to the array that gets initialized
Like so:
typedef Symbols SymbolArr[ Size<Symbols>() ];
static SymbolArr symbolArr;
SymbolArr& symbolArrRef = init_array<Symbols, SymbolArr>(symbolArr);
Edit:
The junk parameter in the recursive initialization function can be removed using:
template< typename E > constexpr E next( E& s ) { return (E)(1 + (size_t)s); }
template< typename E, typename EARR >
constexpr EARR& init_array( EARR& zArr, E sym = E::First )
{
return sym <= E::Last ? init_array( zArr, next( zArr[ as_sizet( sym ) ] = sym ) ) : zArr;
}
I've written a variadic template that accepts a variable number of char parameters, i.e.
template <char... Chars>
struct Foo;
I was just wondering if there were any macro tricks that would allow me to instantiate this with syntax similar to the following:
Foo<"abc">
or
Foo<SOME_MACRO("abc")>
or
Foo<SOME_MACRO(abc)>
etc.
Basically, anything that stops you from having to write the characters individually, like so
Foo<'a', 'b', 'c'>
This isn't a big issue for me as it's just for a toy program, but I thought I'd ask anyway.
I've created one today, and tested on GCC4.6.0.
#include <iostream>
#define E(L,I) \
(I < sizeof(L)) ? L[I] : 0
#define STR(X, L) \
typename Expand<X, \
cstring<E(L,0),E(L,1),E(L,2),E(L,3),E(L,4), E(L,5), \
E(L,6),E(L,7),E(L,8),E(L,9),E(L,10), E(L,11), \
E(L,12),E(L,13),E(L,14),E(L,15),E(L,16), E(L,17)> \
cstring<>, sizeof L-1>::type
#define CSTR(L) STR(cstring, L)
template<char ...C> struct cstring { };
template<template<char...> class P, typename S, typename R, int N>
struct Expand;
template<template<char...> class P, char S1, char ...S, char ...R, int N>
struct Expand<P, cstring<S1, S...>, cstring<R...>, N> :
Expand<P, cstring<S...>, cstring<R..., S1>, N-1>{ };
template<template<char...> class P, char S1, char ...S, char ...R>
struct Expand<P, cstring<S1, S...>, cstring<R...>, 0> {
typedef P<R...> type;
};
Some test
template<char ...S>
struct Test {
static void print() {
char x[] = { S... };
std::cout << sizeof...(S) << std::endl;
std::cout << x << std::endl;
}
};
template<char ...C>
void process(cstring<C...>) {
/* process C, possibly at compile time */
}
int main() {
typedef STR(Test, "Hello folks") type;
type::print();
process(CSTR("Hi guys")());
}
So while you don't get a 'a', 'b', 'c', you still get compile time strings.
A solution based on Sylvain Defresne's response above is possible in C++11:
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
template <unsigned int N>
constexpr char get_ch (char const (&s) [N], unsigned int i)
{
return i >= N ? '\0' : s[i];
}
#define STRING_TO_CHARS_EXTRACT(z, n, data) \
BOOST_PP_COMMA_IF(n) get_ch(data, n)
#define STRING_TO_CHARS(STRLEN, STR) \
BOOST_PP_REPEAT(STRLEN, STRING_TO_CHARS_EXTRACT, STR)
// Foo <STRING_TO_CHARS(3, "abc")>
// expands to
// Foo <'a', 'b', 'c'>
Further, provided the template in question is able to handle multiple terminating '\0' characters, we may ease the length requirement in favor of a maximum length:
#define STRING_TO_CHARS_ANY(STR) \
STRING_TO_CHARS(100, STR)
// Foo <STRING_TO_CHARS_ANY("abc")>
// expands to
// Foo <'a', 'b', 'c', '\0', '\0', ...>
The above examples compile properly on clang++ (3.2) and g++ (4.8.0).
There has been a lot of trials, but it is ultimately doomed to fail I think.
To understand why, one needs to understand how the preprocessor works. The input of the preprocessor can be thought of as a stream. This stream is first transformed in preprocessing-tokens (list availabe in The C++ Programming Language, 3rd Edition, Annexe A Grammar, page 795)
On these tokens, the preprocessor may only apply a very restricted number of operations, apart from the digrams/trigrams stuff, this amount to:
file inclusion (for header directives), this may not appear in a macro as far as I know
macro substitution (which is extremely complicated stuff :p)
#: transforms a token into a string-literal token (by surrounding it by quotes)
##: concatenates two tokens
And that's it.
There is no preprocessor instruction that may split a token into several tokens: this is macro substitution, which means actually having a macro defined in the first place
There is no preprocessor instruction to transform a string-literal into a regular token (removing the quotes) that could then be subject to macro substitution.
I therefore hold the claim that it is impossible (either in C++03 or C++0x), though there might (possibly) be compiler specific extensions for this.
Based on user1653543's solution above.
Some template magic:
template <unsigned int N>
constexpr char getch (char const (&s) [N], unsigned int i)
{
return i >= N ? '\0' : s[i];
}
template<char ... Cs>
struct split_helper;
template<char C, char ... Cs>
struct split_helper<C, Cs...>
{
typedef push_front_t<typename split_helper<Cs...>::type, char_<C>> type;
};
template<char ... Cs>
struct split_helper<'\0', Cs...>
{
typedef std::integer_sequence<char> type;
};
template<char ... Cs>
using split_helper_t = typename split_helper<Cs...>::type;
Some PP magic:
#define SPLIT_CHARS_EXTRACT(z, n, data) \
BOOST_PP_COMMA_IF(n) getch(data, n)
#define STRING_N(n, str) \
split_helper_t<BOOST_PP_REPEAT(n, SPLIT_CHARS_EXTRACT, str)>
#define STRING(str) STRING_N(BOOST_PP_LIMIT_REPEAT, str)
split_helper just helper to cut trailing zeroes. Now STRING("Hello") is a typed compile-time char sequence (std::integer_sequence<char, 'H', 'e', 'l', 'l', 'o'>). Length of string constants is up to BOOST_PP_LIMIT_REPEAT characters.
Homework: implement push_front_t and c_str to get null-terminated string of std::integer_sequence<char, ...>. (Although, you can try to use Boost.MPL)
this used to work in an early version of msvc, I don't know if it still does:
#define CHAR_SPLIT(...) ##__VA_ARGS__
Unfortunately, I believe this cannot be done. The best you can get from the preprocessor is provided by Boost.Preprocessor, most notably through its data types :
array : syntax would be (3, (a, b, c))
list : syntax would be (a, (b, (c, BOOST_PP_NIL)))
sequence : syntax would be (a)(b)(c)
tuple : syntax would be (a, b, c)
From any of these types, you can easily create a macro which would build a comma separated list of single-quote enclosed items (see for example BOOST_PP_SEQ_ENUM), but I believe the input of this macro will have to be one of these types, and all require the characters to be typed individually.
Based on what I was discussing above, the following awful template hackery may be sufficient to pull this off. I haven't tested this (sorry!), but I'm pretty sure it or something close to it might work.
The first step is to build a template class that just holds a tuple of chars:
template <char... Chars> class CharTuple {};
Now, let's build an adapter that can transform a C-style string into a CharTuple. To do this, we'll need the following helper class which is essentially a LISP-style cons for tuples:
template <typename Tuple, char ch> class Cons;
template <char... Chars, char ch> class Cons<CharTuple<Chars... ch>> {
typedef CharTuple<ch, Chars...> type;
}
Let's also assume we have a meta-if statement:
template <bool Condition, typename TrueType, typename FalseType> class If {
typedef typename TrueType::type type;
};
template <typename TrueType, typename FalseType> class If<False> {
typedef typename FalseType::type type;
};
Then the following should let you convert a C-style string into a tuple:
template <typename T> class Identity {
typedef T type;
};
template <char* str> class StringToChars {
typedef typename If<*str == '\0', Identity<CharTuple<>>,
Cons<*str, typename StringToChars<str + 1>::type>>::type type;
};
Now that you can convert a C-style string into a tuple of chars, you can funnel your input string through this type to recover the tuple. We'll need to do a bit more machinery to get this working, though. Isn't TMP fun? :-)
The first step is to take your original code:
template <char... Chars> class Foo { /* ... */ };
and use some template specialization to convert it to
template <typename> class FooImpl;
tempalte <char... Chars> class FooImpl<CharTuple<Chars...>> { /* ... */ };
It's just another layer of indirection; nothing more.
Finally, you should be able to do this:
template <char* str> class Foo {
typedef typename FooImpl<typename StringToChars<str>::type>::type type;
};
I really hope this works. If it doesn't, I still think this is worth posting because it's probably ε-close to a valid answer. :-)
In C++14, this can be done by using an immediately invoked lambda and a static member function, similar to BOOST_HANA_STRING:
#include <utility>
template <char... Cs>
struct my_string {};
template <typename T, std::size_t... Is>
constexpr auto as_chars_impl(std::index_sequence<Is...>) {
return my_string<T::str()[Is]...>{};
}
template <typename T>
constexpr auto as_chars() {
return as_chars_impl<T>(
std::make_index_sequence<sizeof(T::str())-1>{});
}
#define STR(literal) \
[]{ \
struct literal_to_chars { \
static constexpr decltype(auto) str() { \
return literal; \
} \
}; \
return as_chars<literal_to_chars>(); \
}()
Live on Godbolt
Before C++17, the object returned by STR("some literal") can't be constexpr because the lambda can't be constexpr.
Before C++20, you can't just write decltype(STR("some literal")) because lambdas are not allowed in unevaluated contexts.