迭代可变参数模板类型

Rui*_*ade 6 c++ templates initializer-list variadic-templates multiple-arguments

我已经被困在这一段时间了,我的想法用尽了,帮助赞赏!

以下段是示例代码,以简化.

假设如下:

class Base; 
class DerivedA : public Base; 
class DerivedB : public Base;
Run Code Online (Sandbox Code Playgroud)

还有这个:

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

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

基本上我通过使用std :: type_index作为键,在容器中存储派生类的唯一实例.允许我这样做:

manager.remove<DerivedA>();
Run Code Online (Sandbox Code Playgroud)

话虽如此,我希望能够做同样的事情,但允许多个模板直接删除多个实例,如下:

manager.remove<DerivedA, DerivedB>()
Run Code Online (Sandbox Code Playgroud)

我知道可以迭代这里描述的可变参数模板,但我不断收到编译错误......

错误C2440:'初始化':无法从'initializer-list'转换为'std :: initializer_list'

错误C3535:无法从'initializer-list'推断出'auto'的类型

...当我尝试运行此代码时:

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

有任何想法吗?非常感谢你.

Bar*_*rry 2

我猜您刚刚遇到了 MSVC bug。编译错误:

错误 C3535:无法从“初始化列表”推断“自动”的类型

无效。autoC++11 确实允许从花括号初始化列表中扣除 for ,只要所有类型都相同。在你的情况下,std::map::erase返回 a size_t,所以它应该编译。这里是一个基本上包含您的代码的示例。

为了解决这个问题,您可能只需显式提供类型:

size_t dummy[] = {m.erase(typeid(T))...};
Run Code Online (Sandbox Code Playgroud)

或者,以防万一有人没有传入任何类型,请在前面添加一个零:

size_t dummy[] = {0u, m.erase(typeid(T))...};
Run Code Online (Sandbox Code Playgroud)

这样,数组将始终至少有一个元素。Kerrek在他的评论中建议的更典型的用法如下:

int dummy[] = {0, (void(m.erase(typeid(T)), 0)... };
Run Code Online (Sandbox Code Playgroud)

无论您将替换为什么表达式,这都将起作用,因为的m.erase(...)值为。这是为了避免过载问题。(..., 0)0voidoperator,