Alex Rivera | Logout

C++: Can a macro expand "abc" into 'a', 'b', 'c'?

Asked 2011-01-03T08:29:32.313
41

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.

Edit
Report

1 Answer

10

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).

answered 2012-09-07T02:30:01.767

Your Answer