我尝试创建名为std::set
的{{1}}的多路复用,它可以在各种比较对象的透视图中查看元素。例如,一组扑克牌可以排序第一,排名第二,或排第一,排第二; NDos::set_multiplex
可以方便地执行此操作。
NDos::set_multiplex
通过继承多个NDos::set_multiplex
来实现这一点,一个存储元素,另一个存储元素的迭代器。
std::set
是NDos::IterComp
类型,用于比较两个迭代器引用的元素。
以下是代码:
Callable
参数包未正确扩展。 G ++ 6.2报告每次扩展时的错误:(在函数/*...*/
namespace NDos {
template <class T, class Comp0, class... Comps> class set_multiplex :
private std::set<T, Comp0>,
private std::set<
typename std::set<T, Comp0>::iterator,
IterComp<typename std::set<T, Comp0>::iterator, Comps>
>... {
private:
typedef std::set<T, Comp0> Base0;
public:
/*...*/
using typename Base0::iterator;
using typename Base0::const_iterator;
using typename Base0::reverse_iterator;
using typename Base0::const_reverse_iterator;
#define Bases std::set<iterator, IterComp<iterator, Comps>>
/*constructors*/
// copy constructor : default
// move constructor : default
// copy assignment operator : default
// move assignment operator : default
// destructor : default
/*...*/
void clear() noexcept {
Base0::clear();
Bases::clear()...;
}
iterator insert(const T &value) {
return emplace(value);
}
iterator insert(T &&value) {
return emplace(std::move(value));
}
iterator insert(const_iterator pos, const T &value) {
return emplace_hint(pos, value);
}
iterator insert(const_iterator pos, T &&value) {
return emplace_hint(pos, std::move(value));
}
template <class InputIt> void insert(InputIt first, InputIt last) {
while (first != last)
insert(*first++);
}
void insert(std::initializer_list<T> ilist) {
insert(std::make_move_iterator(ilist.begin()), std::make_move_iterator(ilist.end()));
}
template <class... Args> iterator emplace(Args &&...args) {
iterator i0 = Base0::emplace(std::forward<Args>(args)...).first;
Bases::insert(i0)...;
return i0;
}
template <class... Args> iterator emplace_hint(const_iterator pos, Args &&...args) {
iterator i0 = Base0::emplace_hint(pos, std::forward<Args>(args)...).first;
Bases::insert(i0)...;
return i0;
}
iterator erase(iterator pos) {
Bases::erase(pos)...;
return Base0::erase(pos);
}
iterator erase(const_iterator first, const_iterator last) {
while (first != last)
erase(first++);
}
size_type erase(const T &key) {
iterator pos = find(key);
if (pos == end())
return 0;
else {
erase(pos);
return 1;
}
}
void swap(set_multiplex &other) noexcept {
Base0::swap(other);
Bases::swap(other)...;
}
/*...*/
#undef Bases
};
}
,clear
,emplace
,emplace_hint
和erase
)
swap
为什么会发生这种情况?
答案 0 :(得分:2)
在C ++ 11中,你不能简单地这样做:
Bases::clear()...;
对于您以这种方式使用...
的所有其他地方也会发生同样的情况:
Bases::insert(i0)...;
Bases::erase(pos)...;
Bases::swap(other)...;
尝试使用以下内容:
void clear() noexcept {
Base0::clear();
int _[] = { 0, (Bases::clear(), 0)... };
(void)_; // silent warnings, nothing more
}
这是在等待C ++ 17及其折叠表达式时常用的技巧。
swap
函数的特别提及:如果您将other
与Base0
交换,other
理论上会在交换后包含Base0
中的数据。再次使用它进行另一次交换似乎不是一个好主意
也许您应该检查swap
函数的实现。