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

啊,是的,我明白了,这很有道理。我想知道为什么它不会编译,因为它和其他解决方案完全一样。谢谢你澄清。 –