为什么不疯狂呢?
enum class subset_type {
include, all
};
struct include_all_t { constexpr include_all_t() {} };
constexpr include_all_t include_all {};
template<class E>
struct subset {
subset_type type = subset_type::include;
std::variant<
std::array<E, 0>, std::array<E, 1>, std::array<E, 2>, std::array<E, 3>, std::array<E, 4>,
std::vector<E>
> data = std::array<E,0>{};
bool operator()( E e ) const {
if(type==subset_type::all)
return true;
for (E x : *this)
if (x==e) return true;
return false;
}
subset(E e):
type(subset_type::include),
data(std::array<E, 1>{{e}})
{}
subset() = default;
subset(std::initializer_list<E> il):
type(subset_type::include)
{
populate(il);
}
subset(include_all_t):type(subset_type::all) {}
E const* begin() const {
return std::visit( [](auto&& x){ return x.data(); }, data );
}
std::size_t size() const {
return std::visit( [](auto&& x){ return x.size(); }, data );
}
E const* end() const {
return begin()+size();
}
bool empty() const {
return type!=subset_type::all && size()==0;
}
template<class...Src>
void populate(Src const&...srcs) {
std::size_t count = (std::size_t(0) + ... + srcs.size());
auto helper = [&](auto N)->subset& {
std::array<E, N> v;
E* ptr = v.data();
auto add_src = [ptr](auto& src){
for (E x:src)
*ptr++ = x;
};
(add_src(srcs),...);
this->data = v;
};
switch(count) {
case 0: return helper(std::integral_constant<std::size_t, 0>{});
case 1: return helper(std::integral_constant<std::size_t, 1>{});
case 2: return helper(std::integral_constant<std::size_t, 2>{});
case 3: return helper(std::integral_constant<std::size_t, 3>{});
case 4: return helper(std::integral_constant<std::size_t, 4>{});
default: break;
};
std::vector<E> vec;
vec.reserve(count);
auto vec_helper = [&](auto&& c){
for (E x:c) vec.push_back(c);
};
(vec_helper(srcs), ...);
data = std::move(vec);
}
friend subset& operator|=( subset& lhs, subset const& rhs ) {
if (lhs.type==subset_type::all) return lhs;
if (rhs.type==subset_type::all) {
lhs.type = subset_type::all
return lhs;
}
populate( lhs, rhs );
return lhs;
}
friend subset operator|( subset lhs, subset const& rhs ) {
lhs |= rhs;
return std::move(lhs);
}
};
C++17,可能有打字错误。
std::vector<Person> GetPeopleOfAge(subset<Age> age)
你可以使用
Age::Eleven
、
include_all
或
{}
(表示没有),或者使用
{Age::Eleven, Age::Twelve}
(表示两个)来调用它。
它使用小缓冲区优化来处理最多4个元素。
如果不在
all
模式下,您可以使用基于范围的循环迭代子集中的元素。
支持添加
operator&
、
subset_type::none
、
subset_type::exclude
和
operator~
留作练习。