C++可变模板:删除/替换索引处的类型

C++ variadic template: remove/replace type at index

本文关键字:索引 替换 类型 删除 C++      更新时间:2023-10-16

有没有办法:

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类替换了运算符,例如,对于实参<is_true, And, is_true>,我想删除实参(is_true),并用Filter:FilterAnd<is_true, is_true>替换运算符(And),其中实参与从列表中删除的实参相同。因此,我需要替换/删除模板来执行此操作。

提前谢谢。

这在带有std::index_sequence的C++14中要容易得多,所以我已经使用了它。你可以在网上找到很多这样的实现。

我使用std::tuple来整理周围的所有内容。

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

对于Remove,我取tuple_catdecltype,它要么是空元组,要么是包含非移除类型索引的正确元组元素的元组。

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...>{})); 

CCD_ 15留给读者练习。

实时演示