迭代可变模板类型

Iterating variadic template types

本文关键字:类型 迭代      更新时间:2023-10-16

我已经被困在这个问题上一段时间了,我已经没有想法了,感谢帮助!

为了简化,下面是示例代码。

假设如下:

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));
    }
}

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

manager.remove<DerivedA>();

话是这么说的,我希望能够做同样的事情,但允许多个模板直接一次删除多个实例,如:

manager.remove<DerivedA, DerivedB>()

我知道可以像这里描述的那样迭代可变模板,但是我一直得到编译错误…

错误C2440: 'initializing':无法从'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)))... };
}

任何想法?非常感谢。

我猜你刚刚遇到了一个MSVC错误。编译错误:

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

不是有效的。c++ 11允许从带括号的初始化列表中演绎auto,只要所有类型都相同。在您的示例中,std::map::erase返回一个size_t,因此它应该可以编译。下面是一个基本代码的示例。

要解决这个问题,您可以显式地提供类型:

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,过载的问题。