3
constexpr std::tuple<int,char,int,char> t1 = parse("1a2b");
constexpr std::tuple<int,int,int,char> t2 = parse("123a");
constexpr std::tuple<char,int> t3 = parse("a2");

Would something like this be possible?

I am not totally fluent with TMP but I started with the following

template<std::size_t N,typename ...Args> constexpr
std::tuple<Args...> parse(const char* s[N]){
  constexpr char c = s[0];
  constexpr char* new_s[N-1] = "";
  for (int i = 1; i < N; i++) {
    new_s[i] = s[i];
  }
  //my own constexpr isdigit
  if(!isdigit(c)){
    return parse(new_s,c);
  }
  else if(isdigit(c)){
    return parse(new_s,static_cast<int>(c));
  }
  throw std::invalid_argument("");
}
...

I wanted to do this recursively and accumulate the tuple but I quickly realized that every time I would pass in the new tuple the type would change.

Maik Klein
  • 15,548
  • 27
  • 101
  • 197
  • I would think no because the different types of tuples are static, and you are trying to dynamically create new types of tuples, which wouldn't be possible. I might be wrong though. – BWG Oct 04 '14 at 02:40
  • Perhaps overkill for your purposes, but Boost Spirit (esp. Qi) can do things like this: http://boost-spirit.com/home/. Here is the standard example using Qi to parse a string into a struct (a tuple should be possible too): http://www.boost.org/doc/libs/1_48_0/libs/spirit/doc/html/spirit/qi/tutorials/employee___parsing_into_structs.html – jogojapan Oct 04 '14 at 02:46

1 Answers1

5

Since parse must return different types for "1a2b" and "123a", it's obvious that the characters comprising the string literal must be part of the template parameters. It's fairly easy to do something like

constexpr bool my_isdigit(char c){
    return c >= '0' && c <= '9';
}
template<char c, bool = my_isdigit(c)>
struct mapper {
    using type = char;
    static constexpr char value = c;
};

template<char c>
struct mapper<c, true> {
    using type = int;
    static constexpr int value = c - '0';
};

template<char... chars> 
constexpr auto parse(){
    return std::tuple<typename mapper<chars>::type...>(mapper<chars>::value...);
}

constexpr auto p = parse<'1', 'a', '2', 'b'>();

If you really want to use string literals, there are tricks that allow you to explode a string literal into a parameter pack.

Community
  • 1
  • 1
T.C.
  • 133,968
  • 17
  • 288
  • 421
  • 1
    No, it isn't obvious that the function must return a different type for two different strings: `parse` could return a `constexpr` proxy object that, when cast to a `tuple` parses the characters into the `tuple`. That would allow the OP's exact syntax to work. – Yakk - Adam Nevraumont Oct 06 '14 at 00:37
  • @Yakk But then you would have to, well, parse the string yourself to figure out the destination type, no? – T.C. Oct 06 '14 at 01:20
  • Yep. But in the OP, that is what the OP did. Note that if the types (between what the string says, and what the type you turn it into) don't match, you can generate a compile time error. – Yakk - Adam Nevraumont Oct 06 '14 at 01:39