2016-12-30 64 views
-1

我試圖使的std::set多路複用,命名NDos::set_multiplex,其可以以各種比較對象的透視圖中的元素。例如,一組撲克牌可以先排名第一,然後排第二,或者排名第一,排名第二; NDos::set_multiplex可以方便地做到這一點。 NDos::set_multiplex通過繼承多個std::set來完成此操作,其中一個存儲元素,另一個將迭代器存儲到元素。 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報告這些錯誤的每個擴展:(在功能clearemplaceemplace_hinteraseswap

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

爲什麼這些發生?

+0

請發佈更完整的編譯器輸出。某處會有一個行號(並告訴我們是哪一行)。也嘗試將你的代碼減少到關鍵部分。 – Christoph

+0

@Christoph好的,我做到了。 –

回答

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功能的特別提及:如果換成otherBase0other理論上將交換後含有Base0數據。再次使用它進行另一次交換似乎不是一個好主意。
也許你應該檢查一下你的swap函數的實現。

+0

在'Base0 :: swap(other)'期間,沒有元素被複制或移動,並且所有迭代器保持有效。所以這沒有問題。 –