【问题标题】:C++ variadic template: remove/replace type at indexC++ 可变参数模板:删除/替换索引处的类型
【发布时间】:2016-04-13 08:01:59
【问题描述】:

有没有办法:

1) 删除索引处的项目:

// Removes item at index N, e.g. Remove<2, a, b, c, d> results in <a, b, d>
template<std::size_t N, typename ...Args>
struct Remove {
    // ???
};

2) 替换索引处的项目:

// Replaces item at index N with T, e.g. Replace<2, x, a, b, c, d> results in <a, b, x, d>
template<std::size_t N, typename T, typename ...Args>
struct Replace {
    // ???
};

3) 替换范围内的项目

// Replaces items in range [N1, N2] with T, e.g. ReplaceRange<2, 3, x, a, b, c, d> results in <a, b, x>
template<std::size_t N1, std::size_t N2, typename T, typename ...Args>
struct ReplaceRange {
    // ???
};

我希望它被这样使用

class is_true {
public:
    bool operator()() const { return true; }
};


class is_false {
public:
    bool operator()() const { return false; }
};

class And {
};

class Or {
};

Filter f<is_true, And, is_true, Or, is_false>();

现在,我想把它折叠成:

< FilterOr < FilterAnd <is_true, is_true>, is_false > >

在哪里

template<typename Lhs, typename Rhs>
class FilterAnd {
public:
    bool operator()() const { return Lhs() && Rhs(); }
};

template<typename Lhs, typename Rhs>
class FilterOr {
public:
    bool operator()() const { return Lhs() || Rhs(); }
};

所以,我正在尝试执行以下操作:

class Filter {
public:
    template <typename ...Args>
    void apply() {
        holder_ = FilterHolder<typename FoldOperator<Or, FilterOr, typename FoldOperator<And, FilterAnd, Args...>::type >::type >();
    }
}

FoldOperator 基本上删除了运算符参数,并将运算符替换为 Filter 类,例如对于参数&lt;is_true, And, is_true&gt;,我想删除参数(is_true)并将运算符(And)替换为过滤器:FilterAnd&lt;is_true, is_true&gt;,其中参数与从列表中删除的参数相同。所以,我需要替换/删除模板来执行此操作。

提前致谢。

【问题讨论】:

  • 您能否展示如何实现Identity 函数,以便我们知道您期望的输出格式?你的问题并不清楚。
  • @Angew 我不太明白你的意思。我希望这就像template&lt;...&gt; struct Replace { typedef ... type; }
  • @maverik 这正是我的问题。可变模板参数/参数仅存在于模板声明/实例化中,它们不是语言的一流对象。如果函子是Identity,您将其设置为...,即应该保持参数不变?如果我们不知道您想要什么输出格式,我们无法提供修改某些内容的解决方案。
  • @AndyG:我不能使用 C++14,如果可能的话我不想使用std::tuple,因为那样我最终会用元组重写所有代码,否则我需要LLONG_MAX 更多行代码将std::tuple 扩展为可变参数列表(如:stackoverflow.com/questions/687490/…

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


【解决方案1】:

这在 C++14 中使用 std::index_sequence 更容易,所以我使用了它。你可以在网上找到很多实现。

我使用std::tuple 来整理周围的一切。

对于Replace,我使用std::conditional 为每个类型索引选择T 或正确的元组元素。

对于Remove,我将decltypetuple_cat 取为空元组或包含正确元组元素的元组以用于未删除的类型索引。

namespace detail{
template<std::size_t N, typename T, typename Tuple, std::size_t... Idx>
auto replace (std::index_sequence<Idx...>) ->
    std::tuple<std::conditional_t<N == Idx, 
                                  T, 
                                  std::tuple_element_t<N, Tuple>>...>;

template<std::size_t N, typename Tuple, std::size_t... Idx>
auto remove (std::index_sequence<Idx...>) ->
    decltype(std::tuple_cat(
      std::declval<
        std::conditional_t<(N == Idx), 
                           std::tuple<>, 
                           std::tuple<std::tuple_element_t<Idx, Tuple>>
      >
    >()...
    ));
}

template <std::size_t N, typename T, typename... Args>
using Replace = decltype(detail::replace<N,T,std::tuple<Args...>>
                         (std::index_sequence_for<Args...>{}));

template <std::size_t N, typename... Args>
using Remove = decltype(detail::remove<N,std::tuple<Args...>>
                        (std::index_sequence_for<Args...>{})); 

ReplaceRange 留给读者作为练习。

Live Demo

【讨论】:

  • 谢谢,但我不能使用 C++14。知道如何将其移植到 C++11 吗?
  • 在线搜索std::integer_sequence 的实现(我相信SO 上有一些)并使用typename std::trait&lt;T&gt;::type 而不是std::trait_t
猜你喜欢
  • 1970-01-01
  • 2013-09-13
  • 2013-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多