6

我一直堅持這一段時間,我跑出了想法,幫助讚賞!迭代可變模板類型

爲了簡化,下面的段是示例代碼。

假定以下:

class Base; 
class DerivedA : public Base; 
class DerivedB : public Base; 

和此:

class Manager { 
public: 
    std::map<std::type_index, Base*> container; 

    template<typename ...T> 
    void remove() { 
     // Iterate through templates somehow and... 
     container.erase(typeid(T)); 
    } 
} 

基本上我存儲,在容器中,派生類的獨特實例,通過使用標準:: type_index作爲鍵。讓我做這樣的事情:

manager.remove<DerivedA>(); 

雖這麼說,我想能夠直接做同樣的事情,但允許多個模板一次刪除多個實例,因爲這樣的:

manager.remove<DerivedA, DerivedB>() 

我知道這是可能的,描述here通過可變參數模板進行迭代,但我不斷收到編譯錯誤......

error C2440: 'initializing': cannot convert from 'initializer-list' to 'std::initializer_list'

error C3535: cannot deduce type for 'auto' from 'initializer-list'

...當我嘗試運行這段代碼:

template<typename ...T> 
void remove() { 
    // Iterate through templates somehow and... 
    auto list = {(container.erase(typeid(T)))... }; 
} 

任何想法? 非常感謝。

+2

'int dummy [] = {(c.erase(typeid(T)),0)...};' –

+0

Woah,您的解決方案非常適合開箱即用...我嘗試了類似的東西更早但沒有0.有什麼區別? –

+0

'0'是一個'int'。 –

回答

2

我猜你剛剛遇到了一個MSVC錯誤。編譯錯誤:

error C3535: cannot deduce type for 'auto' from 'initializer-list'

無效。只要所有類型相同,C++ 11就允許從braced-init-list中扣除auto。在你的情況下,std::map::erase返回一個size_t,所以它應該編譯。基本上你的代碼是Here是一個例子。

要解決這個問題,你可能只是能夠明確提供類型:

size_t dummy[] = {m.erase(typeid(T))...}; 

或者,萬一有人經過中沒有的類型,在前面加上一個零:

size_t dummy[] = {0u, m.erase(typeid(T))...}; 

那方式,數組總是至少有一個元素。更典型的用法,這Kerrek在他的評論中建議,將是以下幾點:

int dummy[] = {0, (void(m.erase(typeid(T)), 0)... }; 

,無論你將取代m.erase(...)與表達,將工作,因爲(..., 0)0void是爲了避免超載operator,的問題。

+0

啊,是的,我明白了,這很有道理。我想知道爲什麼它不會編譯,因爲它和其他解決方案完全一樣。謝謝你澄清。 –