c++ - Deduce type from literal string -


i want deduce parameter types of function string. similar printf does.

currently following:

#include <utility>  // calculate length of literal string constexpr int length(const char* str) {   return *str ? 1 + length(str + 1) : 0; }  struct ignore { };  template <char c1, char c2> struct type {   typedef ignore type; };  // %d -> int template <> struct type<'%','d'> {   typedef int type; };  // %f -> float template <> struct type<'%','f'> {   typedef float type; };  // type string template <const char * const * const str, int pos, int n = length(str[pos])> struct gettype {   typedef ignore type; };  template <const char * const * const str, int pos> struct gettype<str, pos, 2> {   typedef typename type<str[pos][0],str[pos][1]>::type type; };  // dummy class template <typename... targs> struct foo {     void send(targs...) const {} };  // deduce type each literal string array template <const char * const * strs,  std::size_t n, std::size_t... index> constexpr auto parseit(std::index_sequence<index...>) {   return foo<typename gettype<strs, index>::type...>(); }  template <const char * const * strs, std::size_t n> constexpr auto makefoo(const char * const (&a)[n]) {    return parseit<strs, 2>(std::make_index_sequence<n>{}); } 

the problem is, have write ignore() on function call...

constexpr const char *message[] = {"%d", " hello ", "%f", "good"}; constexpr auto foo = makefoo<message>(message);  int main() {      foo .send(10, ignore(), 20.0f, ignore());    return 0; } 

live example

what want (compile-time check only):

myfoo foo("%d hello world %f %s"); foo.send(10, 20.f, "hello"); 

you may char_sequence:

template <char ... > struct char_sequence {};  template <typename ... tuples> using tuple_concat = decltype(std::tuple_cat(std::declval<tuples>()...));  template <typename> struct format_helper;  template <typename t> using format_helper_t = typename format_helper<t>::type;  // end case template <> struct format_helper<char_sequence<>> {     using type = std::tuple<>; };  // general case template <char c, char...cs> struct format_helper<char_sequence<c, cs...>> {     using type = format_helper_t<char_sequence<cs...>>; };  template <typename t> struct dependant_false : std::false_type {};  // unknown format % template <char...cs> struct format_helper<char_sequence<'%', cs...>> {     static_assert(dependant_false<char_sequence<cs...>>::value, "unsupported escape"); };  // %% % template <char...cs> struct format_helper<char_sequence<'%', '%', cs...>> {     using type = format_helper_t<char_sequence<cs...>>; };  // %f float template <char...cs> struct format_helper<char_sequence<'%', 'f', cs...>> {     using type = tuple_concat<std::tuple<float>, format_helper_t<char_sequence<cs...>>>; };  // %d int template <char...cs> struct format_helper<char_sequence<'%', 'd', cs...>> {     using type = tuple_concat<std::tuple<int>, format_helper_t<char_sequence<cs...>>>; }; 

that allow retrieve list of type literal string.

and then

// ...  template <typename... ts> struct foo {     // ...     void send(ts... args) const; };  template <typename t> struct tag{};  template <typename... ts> foo<ts...> makefoo(tag<std::tuple<ts...>>, const std::string& s) {     return foo<ts...>(s); }  template <char ... cs> auto makefoo(char_sequence<cs...>) {     const char s[] = {cs..., '\0'};     return makefoo(tag<format_helper_t<char_sequence<cs...>>>{}, s); } 

demo


Comments

Popular posts from this blog

java - Run spring boot application error: Cannot instantiate interface org.springframework.context.ApplicationListener -

reactjs - React router and this.props.children - how to pass state to this.props.children -

Excel VBA "Microsoft Windows Common Controls 6.0 (SP6)" Location Changes -