【问题标题】:Iterating variadic template types迭代可变参数模板类型
【发布时间】:2015-07-13 02:22:51
【问题描述】:

我已经被困了一段时间了,我的想法已经用完了,感谢您的帮助!

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

假设如下:

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 的描述遍历可变参数模板,但我不断收到编译错误...

错误 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)))... };
}

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

【问题讨论】:

  • int dummy[] = { (c.erase(typeid(T)), 0)... };
  • 哇,您的解决方案开箱即用,效果非常好……我之前尝试过类似的方法,但没有 0。有什么区别?
  • 您的代码应该没问题,可能是 MSVC 错误(erase 返回 size_t,所以应该没问题)。它应该只是将list 推断为std::initialize_list&lt;size_t&gt;...

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


【解决方案1】:

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

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

无效。只要所有类型都相同,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, 过载的问题。

【讨论】:

  • 啊,是的,我明白了,有道理。我想知道为什么它不能编译,因为它和其他人的解决方案完全一样。谢谢你的澄清。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-29
  • 1970-01-01
  • 2016-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多