gpt4 book ai didi

c++ - 用于创建 integral_constants 的任意元组的通用实用程序

转载 作者:可可西里 更新时间:2023-11-01 17:57:25 25 4
gpt4 key购买 nike

利用Scott Schurr's str_const我有一个 constexpr 字符串。

class StrConst
{
public:
template<size_t N>
constexpr StrConst(const char (&str)[N])
: str_(str)
, len_(N - 1)
{
static_assert(N > 1, "not a string");
}

constexpr operator const char*() const
{
return str_;
}

constexpr size_t size() const
{
return len_;
}

constexpr char operator[] (size_t i) const
{
return i < len_ ? str_[i] : throw std::out_of_range("invalid index");
}

private:
const char* const str_;
const size_t len_;
};

我有另一个 constexpr 函数,它返回在字符串中找到的第一个插入符号的位置,从位置 n 开始:

constexpr int caretPos(const StrConst& str, size_t n = 0)
{
if (n == str.size())
return -1;

if (str[n] == '^')
return n;

return caretPos(str, n+1);
}

我可以使用 caretPos 的结果为 std::integral_constantsstd::tuple 创建一个 typedef,其中大小元组的个数是字符串中插入符的个数,每个元组元素是一个整型常量,其值是插入符在字符串中的位置。

这里我手动构造这个元组:

int main()
{
constexpr StrConst s("hello^world^");

constexpr int pos1 = caretPos(s);
constexpr int pos2 = caretPos(s, pos1+1);

using P1 = std::integral_constant<int, pos1>;
using P2 = std::integral_constant<int, pos2>;

using PosTuple = std::tuple<P1, P2>;

static_assert(std::tuple_element_t<0, PosTuple>::value == 5, "");
static_assert(std::tuple_element_t<1, PosTuple>::value == 11, "");
}

问题:

我现在想将此概括为具有任意数量插入符号的任何输入字符串。

template<size_t... Ns>
using PosTuple = std::tuple<std::integral_constant<int, Ns>...>;

如何使用 caretPos 或其他方式生成此处所需的 Ns... 序列?

Working example

最佳答案

有趣的问题。

避免使用 StrConst , 在下面的示例中,您可以看到一种获取 std::tuple<std::integral_constant<std::size_t, Pos1>, std::integral_constant<std::size_t, Pos2>, ...> 的方法类型。

首先,使用arrayConverter()转换 char const *std::array<char, N> ( lc ,在下面的代码中);第二:使用tupleIndexGenerator<lc.size(), lc, '^'>::type获取请求的类型。

所以,如果"hello^world^"是字符串,来自 tupleIndexGenerator<lc.size(), lc, '^'>::type你得到 std::tuple<std::integral_constant<std::size_t, 5U>, std::integral_constant<std::size_t, 11U>>

代码

#include <iostream>
#include <array>
#include <tuple>

template <typename, typename>
struct typeConcat;

template <typename T0, template <typename ...> class C, typename ... Ts>
struct typeConcat<T0, C<Ts...>>
{ using type = C<T0, Ts...>; };

template <std::size_t N, std::array<char, N> const & A, char CH,
std::size_t Pos = 0U, bool EQ = ((Pos < N) && (A.at(Pos) == CH))>
struct tupleIndexGenerator;

template <std::size_t N, std::array<char, N> const & A, char CH>
struct tupleIndexGenerator<N, A, CH, N, false>
{ using type = std::tuple<>; };

template <std::size_t N, std::array<char, N> const & A, char CH,
std::size_t Pos>
struct tupleIndexGenerator<N, A, CH, Pos, false>
{ using type = typename tupleIndexGenerator<N, A, CH, Pos+1U>::type; };

template <std::size_t N, std::array<char, N> const & A, char CH,
std::size_t Pos>
struct tupleIndexGenerator<N, A, CH, Pos, true>
{ using type = typename typeConcat<
std::integral_constant<std::size_t, Pos>,
typename tupleIndexGenerator<N, A, CH, Pos+1U>::type>::type; };

template <typename T, size_t N, size_t ... Is>
constexpr auto arrayConverter (T const (&arr)[N],
std::index_sequence<Is...> const &)
{ return std::array<T, N> { { arr[Is]... } }; }

template <typename T, size_t N>
constexpr auto arrayConverter (T const (&arr)[N])
{ return arrayConverter(arr, std::make_index_sequence<N>{}); }

constexpr auto lc = arrayConverter("hello^world^");

int main ()
{
static_assert(std::is_same<
typename tupleIndexGenerator<lc.size(), lc, '^'>::type,
std::tuple<std::integral_constant<std::size_t, 5U>,
std::integral_constant<std::size_t, 11U>>>::value,
"!");
}

关于c++ - 用于创建 integral_constants 的任意元组的通用实用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43312515/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com