2016-12-30 5 views
-1

Я попытался сделать мультиплекс std::set с именем NDos::set_multiplex, который может просматривать элементы в перспективе различных объектов сравнения. Например, набор игральных карт можно было бы отсортировать с рангом первым и набрать второй, или заняться первым и вторым; NDos::set_multiplex позволяет сделать это удобно. NDos::set_multiplex делает это, наследуя несколько std::set s, один хранит элементы, а остальные хранят итератор для элементов. NDos::IterComp - это тип Callable, который сравнивает элементы, на которые ссылаются два итератора.Расширение пакета параметров не работает

Вот код:

/*...*/ 
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 
    }; 
} 

Пакеты параметров не расширены должным образом. G ++ 6.2 Отчеты те ошибки каждого расширения: (В функции clear, emplace, emplace_hint, erase и swap)

error: expected ';' before '...' token 
error: parameter packs not expanded with '...' 

Почему это происходит?

+0

Пожалуйста, напишите более полный вывод компилятора. Там где-то будет номер строки (и покажите нам, какая строка). Также попробуйте уменьшить свой код до критической части. – Christoph

+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.

+0

Во время 'Base0 :: swap (other)' никакие элементы не копируются и не перемещаются, и все итераторы остаются в силе. Так что это не проблема. –

Смежные вопросы