C++ 在模板中隐式获取字符串的长度

C++ 在模板中隐式获取字符串的长度,c++,templates,constexpr,C++,Templates,Constexpr,好的,假设我有一个神奇的模板,它接受一个字符数组,并将其转换为模板参数列表。例如:“thing”被翻译成列表: 模板 阵列列表; 您可以这样使用它: constexpr char string[] = "this is a test"; typedef ArrayToList<string,14> list; constexpr char string[]=“这是一个测试”; typedef数组列表; 有没有办法隐式检测字符串长度,这样我只需: typedef ArrayToL

好的,假设我有一个神奇的
模板
,它接受一个
字符
数组,并将其转换为模板参数列表。例如:
“thing”
被翻译成
列表

模板
阵列列表;
您可以这样使用它:

constexpr char string[] = "this is a test";
typedef ArrayToList<string,14> list;
constexpr char string[]=“这是一个测试”;
typedef数组列表;
有没有办法隐式检测字符串长度,这样我只需:

typedef ArrayToList<string> list;
typedef数组列表;

不幸的是,这无法完成: 您希望有一个非类型模板参数(字符串)。从语法上讲,指定非类型模板参数的唯一方法是声明其类型,但是,类型取决于字符串本身的长度,您需要两个模板参数(长度和字符串),或者如果将字符串转换为
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;
模板结构列表{};
//只是一份声明
模板结构将\添加到\列表中;
//专门用于字符列表的情况,插入v
模板结构将\添加到\列表{
使用类型=列表;
};
//将str[length-rindex]捕获到列表的头部
模板
结构到列表{
使用type=typename将\添加到\列表<
str[length-rindex],
列表的类型名称::类型
>::类型;
};
//递归的基
模板
结构到列表{
使用类型=列表;
};
模板
使用ArrayToList=
typename to_list::type;
//现在,举个例子
constexpr char str[]=“你好”;
模板结构显示类型错误;
在错误中显示类型错误;

不幸的是,这无法完成: 您希望有一个非类型模板参数(字符串)。从语法上讲,指定非类型模板参数的唯一方法是声明其类型,但是,类型取决于字符串本身的长度,您需要两个模板参数(长度和字符串),或者如果将字符串转换为
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;
模板结构列表{};
//只是一份声明
模板结构将\添加到\列表中;
//专门用于字符列表的情况,插入v
模板结构将\添加到\列表{
使用类型=列表;
};
//将str[length-rindex]捕获到列表的头部
模板
结构到列表{
使用type=typename将\添加到\列表<
str[length-rindex],
列表的类型名称::类型
>::类型;
};
//递归的基
模板
结构到列表{
使用类型=列表;
};
模板
使用ArrayToList=
typename to_list::type;
//现在,举个例子
constexpr char str[]=“你好”;
模板结构显示类型错误;
在错误中显示类型错误;

您需要支持的最大长度是多少?不要问月亮,问你需要什么。在你的情况下,它将是
sizeof(string)-1
。不过,我真的很想看看这个模板。@SergeyA是将字符数组放入模板列表的神奇模板吗?如果你想要的话,我可以把它贴出来……(虽然这是相当可观的)@DarthRubik,我很好奇。你不必:)@SergeyA你需要支撑的最大长度是多少?不要问月亮,问你需要什么。在你的情况下,它将是
sizeof(string)-1
。不过,我真的很想看看这个模板。@SergeyA是将字符数组放入模板列表的神奇模板吗?如果你想要的话,我可以把它贴出来……(虽然这是相当可观的)@DarthRubik,我很好奇。你不必:)@SergeyA