rom*_*ric 4 c++ template-meta-programming c++11
给定具有可变参数的参数包,如何找到包中唯一值的数量.我正在寻找一些类似的东西
no_of_uniques<0,1,2,1,2,2>::value // should return 3
Run Code Online (Sandbox Code Playgroud)
我的基本实现看起来像这样
template <size_t ... all>
struct no_of_uniques;
// this specialisation exceeds -ftemplate-depth as it has no terminating condition
template <size_t one, size_t ... all>
struct no_of_uniques<one,all...> {
static const size_t value = no_of_uniques<one,all...>::value;
};
template <size_t one, size_t two, size_t three>
struct no_of_uniques<one,two,three> {
static const size_t value = (one==two && one==three && two==three) ? 1:
(one!=two && two==three) ? 2:
(one==two && one!=three) ? 2:
(one==three && two!=three) ? 2: 3;
};
template <size_t one, size_t two>
struct no_of_uniques<one,two> {
static const size_t value = one==two ? 1: 2;
};
template <size_t one>
struct no_of_uniques<one> {
static const size_t value = 1;
};
Run Code Online (Sandbox Code Playgroud)
在这里,我专门讨论了最多三个参数,但可以理解的是,代码随着参数的数量呈指数增长.我想meta单独使用一个STL没有第三方库的解决方案Boost.MPL.
类似的问题虽然在检查唯一类型的上下文中,而不是查找参数包的唯一值的数量,可以在这里找到:
在查找参数包的唯一值的数量的过程中,我们可能需要首先对包进行排序,并在此另一个问题中提供了一个很好的实现.
kmd*_*eko 10
这是一种简单的O(n ^ 2)方法
template <size_t...>
struct is_unique : std::integral_constant<bool, true> {};
template <size_t T, size_t U, size_t... VV>
struct is_unique<T, U, VV...> : std::integral_constant<bool, T != U && is_unique<T, VV...>::value> {};
template <size_t...>
struct no_unique : std::integral_constant<size_t, 0> {};
template <size_t T, size_t... UU>
struct no_unique<T, UU...> : std::integral_constant<size_t, is_unique<T, UU...>::value + no_unique<UU...>::value> {};
Run Code Online (Sandbox Code Playgroud)
所以使用你的例子:
no_unique<0, 1, 2, 1, 2, 2>::value; // gives 3
Run Code Online (Sandbox Code Playgroud)
其中大部分是我已经为不同的问题写的机器,剥夺了"计数"部分.
一个包含sizeof快捷方式的包:
template<class... Ts> struct pack {
static constexpr size_t size = sizeof...(Ts);
};
Run Code Online (Sandbox Code Playgroud)
将类型添加到一个类型的包中,但仅当它已经不存在时:
template<class T, class PT> struct do_push;
template<class T, class...Ts>
struct do_push<T, pack<Ts...>>{
using type = std::conditional_t<std::disjunction_v<std::is_same<Ts, T>...>,
pack<Ts...>,
pack<T, Ts...>
>;
};
template<class T, class PT> using push = typename do_push<T, PT>::type;
Run Code Online (Sandbox Code Playgroud)
现在制作一包独特的类型:
template<class P, class PT = pack<> >
struct unique_types_imp { using type = PT; };
template<class PT, class T, class... Ts>
struct unique_types_imp <pack<T, Ts...>, PT>
: unique_types_imp <pack<Ts...>, push<T, PT>> {};
template<class P>
using unique_types = typename unique_types_imp<P>::type;
Run Code Online (Sandbox Code Playgroud)
最后:
template<size_t S>
using size_constant = std::integral_constant<size_t, S>;
template<size_t... all>
struct no_of_uniques{
static constexpr size_t value = unique_types<pack<size_constant<all>...>>::size;
};
Run Code Online (Sandbox Code Playgroud)