c++ - 迭代可变模板类型

标签 c++ templates variadic-templates initializer-list multiple-arguments

我已经坚持了一段时间,但我已经没有想法了,感谢帮助!

为了简化,以下部分是示例代码。

假设如下:

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>()

我知道可以按照 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)))... };
}

有什么想法吗? 非常感谢。

最佳答案

我猜您刚刚遇到了一个 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, 的问题。

关于c++ - 迭代可变模板类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31368699/

相关文章:

c++ - 询问用户要在数组中搜索的整数

c++ - Qt: QListView 改变 MultiSelection 选择模式的行为

c++ - 未在此范围内声明“收银员”

c++ - 动态检查使用可变参数继承的类的类型的最佳方法是什么?

c++ - 如何在c++11中实现工厂+装饰器模式

c++ - 使用模板将 lambda 解析为函数

c++ - 启用_if : case of templated method of a template base inherited several times

C++ 模板和派生类成员初始化

c++ - 从可变参数模板中扩展的 decltype 继承

c++ - 模板推演失败