我正在寻找一种方法来从模板参数包中删除(让我们现在所有出现的)类型。最终结果将是一个如下所示的结构:
template<typename T, typename...Ts>
struct RemoveT
{
using type = /* a new type out of Ts that does not contain T */
}
让我们说边缘情况RemoveT<int, int>
将通过返回void
来处理(未在后面的代码中处理)。我的初始设计看起来像这样:
// --------------------------------------------------------------
// 1. A "way" of typedefing variadic number of types ------------
template<typename...Ts>
struct pack {
using type = Ts;
};
// --------------------------------------------------------------
// --------------------------------------------------------------
template<typename T, typename...Ts> struct RemoveT;
template<typename T, typename T1, typename...Ts>
struct RemoveT {
using type = typename pack<T1, typename RemoveT<T, Ts...>::type>::type;
};
template<typename T, typename T1>
struct RemoveT<T, T1> {
using type = T1;
};
template<typename T, typename...Ts>
struct RemoveT<T, T, Ts...> {
using type = typename RemoveT<Ts...>::type;
};
// --------------------------------------------------------------
现在我甚至无法开始测试此代码,因为the pack
structure is not valid C++
以防这对答案有帮助,其他一些解决方法
pack
甚至根本没用。我们可以在RemoveT
结构周围移动,创建一个仅包含所需类型的新RemoveT
。然后,问题在从struct 对于可变类型Ts
和类型T
:我可以从Us
中创建Ts
,忽略T
吗? < / p>
答案 0 :(得分:10)
以下提供了从T
中删除Ts...
的非递归和直接方法,并且与Jarod42的解决方案一样,产生std::tuple<Us...>
,但无需使用typename ...::type
:
#include <tuple>
#include <type_traits>
template<typename...Ts>
using tuple_cat_t = decltype(std::tuple_cat(std::declval<Ts>()...));
template<typename T, typename...Ts>
using remove_t = tuple_cat_t<
typename std::conditional<
std::is_same<T, Ts>::value,
std::tuple<>,
std::tuple<Ts>
>::type...
>;
int main()
{
static_assert(std::is_same<
remove_t<int, int, char, int, float, int>,
std::tuple<char, float>
>::value, "Oops");
}
答案 1 :(得分:8)
以下可能会有所帮助:
namespace detail
{
template <typename T, typename Tuple, typename Res = std::tuple<>>
struct removeT_helper;
template<typename T, typename Res>
struct removeT_helper<T, std::tuple<>, Res>
{
using type = Res;
};
template<typename T, typename... Ts, typename... TRes>
struct removeT_helper<T, std::tuple<T, Ts...>, std::tuple<TRes...>> :
removeT_helper<T, std::tuple<Ts...>, std::tuple<TRes...>>
{};
template<typename T, typename T1, typename ...Ts, typename... TRes>
struct removeT_helper<T, std::tuple<T1, Ts...>, std::tuple<TRes...>> :
removeT_helper<T, std::tuple<Ts...>, std::tuple<TRes..., T1>>
{};
}
template <typename T, typename...Ts> struct RemoveT
{
using type = typename detail::removeT_helper<T, std::tuple<Ts...>>::type;
};
static_assert(std::is_same<std::tuple<char, float>,
typename RemoveT<int, int, char, int, float, int>::type>::value, "");
答案 2 :(得分:2)
首先,将所有特定模板名称移出到列表中。可能有一种方法可以指定模板名称和参数列表,为该模板提供参数,但我还没有弄清楚:
template <typename...TArgs> struct TypeList
{
typedef std::tuple<TArgs...> tuple_type;
// whatever other types you need
};
接下来,定义添加:
template<typename T, typename TList> struct AddT;
template<typename T, typename ... TArgs>
struct AddT< T, TypeList<TArgs...> >
{
typedef TypeList<T, TArgs... > type;
};
然后,定义删除:
template<typename R, typename ... TArgs> struct RemoveT;
template<typename R>
struct RemoveT<R>
{
typedef TypeList<> type;
};
template<typename R, typename T, typename ...TArgs>
struct RemoveT<R, T, TArgs...>
{
typedef typename std::conditional
< std::is_same<R, T>::value
, typename RemoveT<R, TArgs...>::type
, typename AddT<T, typename RemoveT<R, TArgs...>::type>::type
>::type type;
};
最后,测试:
int result = 0;
result = std::is_same
< std::tuple<long,double>
, RemoveT<int, int, long, int, double, int>::type::tuple_type
>::value;
assert ( result );