【问题标题】:A way to get parameter pack from tuple / array?从元组/数组中获取参数包的方法?
【发布时间】:2018-08-29 13:46:44
【问题描述】:

所以,我正试图像一个人那样弄乱constexpr 字符串,而且到目前为止真的只有这个:

template<char... CS> struct text {
    static constexpr char c_str[] = {CS...};
    static constexpr int size = sizeof...(CS);

};

这样就可以编译了

text<'a','b','c'> t;

std::cout<< t.c_str  <<std::endl;

并按预期输出'abc'

我想知道是否有一种不复杂的方式来做相反的事情;有一个函数返回一个文本类型,其中包含必要的char 模板参数,给定一个char 数组。

【问题讨论】:

  • 您可能想检查一下:isocpp.org/blog/2018/03/… 编译时字符串将受益于标准的未来发展。在那之前,令人费解的是要走的路
  • 你在哪里坚持返回这种类型?你的 char 数组在编译时是已知的,对吧?
  • @DrewDormann 我想我只是不明白你如何从一个带有 char 数组参数的函数转到一个“文本”对象,数组中的每个字符都作为新对象的模板传递争论。你会建议什么样的解决方案?
  • 我怀疑解决方案会非常复杂。您正在尝试将函数参数(将在运行时检查的东西)转换为必须在编译时知道的返回类型。
  • 或者换句话说,函数不会返回像text这样的模板。它们必须返回特定类型。

标签: c++ c++11 variadic-templates template-meta-programming constexpr


【解决方案1】:

不完全是你问的......而且有点令人费解,我想......但如果你定义一个 constexpr 函数来检测字符串的长度

constexpr std::size_t strLen (char const * str, std::size_t len = 0U)
 { return *str ? strLen(++str, ++len) : len; }

以及定义所需类型的辅助结构

template <char const *, typename>
struct foo_helper;

template <char const * Str, std::size_t ... Is>
struct foo_helper<Str, std::index_sequence<Is...>>
 { using type = text<Str[Is]...>; };

你可以通过字符串来获取你的类型

template <char const * Str>
struct foo : public foo_helper<Str, std::make_index_sequence<strLen(Str)>>
 { };

不幸的是,您不能以这种方式将字符串文字传递给它

foo<"abc">::type

但你必须从全局变量中传递

constexpr char abcVar[] = "abc";

并使用全局变量调用foo

foo<abcVar>::type 

此解决方案使用 std::index_sequencestd::make_index_sequence,仅从 C++14 开始可用,但在 C++11 中编写它们的替代品并不难。

以下是一个完整的工作示例

#include <utility>
#include <iostream>
#include <type_traits>

template <char ... CS>
struct text
 {
   static constexpr char c_str[] = {CS...};
   static constexpr int size = sizeof...(CS);
 };

constexpr std::size_t strLen (char const * str, std::size_t len = 0U)
 { return *str ? strLen(++str, ++len) : len; }

template <char const *, typename>
struct foo_helper;

template <char const * Str, std::size_t ... Is>
struct foo_helper<Str, std::index_sequence<Is...>>
 { using type = text<Str[Is]...>; };


template <char const * Str>
struct foo : public foo_helper<Str, std::make_index_sequence<strLen(Str)>>
 { };

constexpr char abcVar[] = "abc";

int main()
 {
   static_assert(std::is_same<foo<abcVar>::type,
                              text<'a', 'b', 'c'>>{}, "!");
 }

题外话:我建议在c_str[]中添加一个结尾零

static constexpr char c_str[] = {CS..., 0};

如果您想将其用作std::stringc_str() 方法。

【讨论】:

    猜你喜欢
    • 2018-11-19
    • 1970-01-01
    • 2012-02-03
    • 2013-09-30
    • 2015-07-13
    • 2014-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多