在模板中隐式绘制字符串的长度

Take the length of a string implicitly in templates

本文关键字:字符串 绘制      更新时间:2023-10-16

好吧,假设我有这个魔术template,它采用char数组,并将其变成模板参数列表。例如:"thing"转换为list<'t','h','i','n','g'>

template<const char*, size_t>
ArrayToList;

您像这样使用它:

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

是否有任何方法可以隐含地检测字符串长度,以便我要做的就是:

typedef ArrayToList<string> list;

不幸的是,它不能完成:您想拥有一个非类型模板参数(字符串)。从语法上讲,指定非类型模板参数的唯一方法是声明其类型,但是,该类型取决于字符串本身的长度,您需要两个模板参数(长度和字符串),或者如果转换了字符串到const char *,字符串的长度在参数中丢失。

有建议允许捕获非类型模板参数的类型本身需要一个模板参数以防止强迫这些额外模板参数的语法,例如在您的情况下。

我遇到了同样的问题,试图捕获成员的指针,也有必要说出什么是总体。

一个建议:如果您将参数的顺序还原为ArrayToList,我认为您可以通过捕获其长度的非类型参数来简化代码,如下所示:

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;