具有部分固定类型的递归数据类型。

问题描述 投票:3回答:1

我有以下代码

#include <string_view>
#include <utility>

namespace std
{
  template <typename T1, typename T2>
  pair(T1 t1, T2 t2) -> pair<T1, T2>;
}

template<typename ... T>
struct node {};

template<typename head_t, typename ... tail_t>
struct node<head_t, tail_t ...>
{
  node(const head_t& head, const tail_t& ... tail)
    : head(head)
    , tail(tail...)
  {}

  head_t head;
  node<tail_t ... > tail;
};

template <typename... T>
node(T... t) -> node<T...>;

int main()
{
  node n{
    std::pair{std::string_view{"a"}, int{4}},
    std::pair{std::string_view{"b"}, int{5}},
    std::pair{std::string_view{"dqwd"}, node{
      std::pair{std::string_view{"asdas"}, float{3.4}}
    }
  };
  return 0;
}

我用

g++ -Wall -Wextra -Wpedantic -std=gnu++17 -Wl,--wrap=malloc

我的数据结构是一个递归的列表,其中包括一个 std::pair 类型的第一个元素 std::string_view.现在我想摆脱 std::pairstd::string_view 因为它们的类型总是相同的,我怎样才能做到这一点呢? 例如

node n{
  {"a", int{4}},
  {"b", int{5}},
  {"dqwd", node{
    {"asdas", float{3.4}}
  }
};
c++ c++17 template-meta-programming recursive-datastructures
1个回答
1
投票

摆脱 string_view至少,是相当容易的。它还有一个好处,那就是可以消除你的操纵。std 命名空间,即使它是合法的,也会让我很不舒服。

平心而论,你对 std 不是 可怕 以此为例 这里,因为你可以很容易地使用你自己的 std::pair 等价,并达到相同的语法。

#include <string_view>

template<typename T>
auto leaf(std::string_view s, T d) {
    return std::make_pair(s, std::move(d));
}

template<typename ... T>
struct node {};

template<typename head_t, typename ... tail_t>
struct node<head_t, tail_t ...>
{
  node(head_t head, tail_t... tail)
    : head(std::move(head))
    , tail(std::move(tail)...)
  {}

  head_t head;
  node<tail_t ... > tail;
};

template <typename... T>
node(T... t) -> node<T...>;

int main()
{
    node n{
        leaf("a", 4),
        leaf("b", 5),
        leaf("c", node{
            leaf("aaa", 12.4f)
        })
    };

  return 0;
}

对于摆脱叶子,以下内容可能适用。https:/stackoverflow.coma518572454442671。但我怀疑不是。

作为一个侧注,你的节点类可以简单地委托给 std::tuple<> 做的大部分事情都是一样的。这将避免你不得不处理递归剥离参数的问题,而且你甚至不需要推理指南。

template<typename... T>
struct node
{
  node(std::pair<std::string_view, T>... args)
    : childs_(std::move(args)...) {}

  std::tuple<std::pair<std::string_view, T>...> childs_;
};
© www.soinside.com 2019 - 2024. All rights reserved.