Take the length of a string implicitly in templates

故事扮演 提交于 2019-12-08 06:09:36

问题


Ok, suppose I have this magic template that takes a char array and turns it into a template parameter list. For example: "thing" is translated to list<'t','h','i','n','g'>:

template<const char*, size_t>
ArrayToList;

You use it like this:

constexpr char string[] = "this is a test";
typedef ArrayToList<string,14> list;

Is there any way to somehow detect the string length implicitly so that all I have to do is:

typedef ArrayToList<string> list;

回答1:


Unfortunately, it can't be done: You would like to have a non-type template parameter (the string). Syntactically speaking, the only way to specify a non-type template parameter is to declare its type, however, either the type depends on the length of the string itself and you need two template parameters (length and string), or if you convert the string to const char *, the length of the string is lost in the parameter.

There are proposals to allow the capture of non-type template parameters whose type itself requires a template parameter to prevent forcing the syntax of those extra template arguments, like in your case.

I had the same kind of problem trying to capture pointers to members, it is necessary to also say what is the aggregate.

One recommendation: If you revert the order of the arguments to ArrayToList, I think you can simplify the code by capturing the non-type parameter with its length, as here:

template<char...> struct list {};

// just a declaration
template<char, typename> struct add_to_list;

// specializes for the case of a list of chars, to insert v
template<char v, char... pack> struct add_to_list<v, list<pack...>> {
  using type = list<v, pack...>;
};

// captures str[length - rindex] into the head of the list
template<unsigned rindex, unsigned length, const char str[length]>
  struct to_list {
    using type = typename add_to_list<
      str[length - rindex],
      typename to_list<rindex - 1, length, str>::type
    >::type;
  };

// base of the recursion
template<unsigned length, const char str[length]>
  struct to_list<1, length, str> {
    using type = list<>;
  };

template<unsigned string_length, const char str[string_length]>
  using ArrayToList =
    typename to_list<string_length, string_length, str>::type;


// now, an example
constexpr char str[] = "hello";


template<typename> struct show_type_in_error;
show_type_in_error<ArrayToList<sizeof(str), str>> error;


来源:https://stackoverflow.com/questions/37892646/take-the-length-of-a-string-implicitly-in-templates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!