【问题标题】:Getting type_info from variadic template breaks the compiler... why?从可变参数模板获取 type_info 会破坏编译器......为什么?
【发布时间】:2013-12-19 02:23:38
【问题描述】:

所以我实际上是在尝试将参数包的 rtti 推入 type_info* 列表中。但是由于某种原因,它似乎没有编译(或者编译器中途放弃了)。无论哪种方式,我似乎都无法弄清楚。有没有人有办法解决这个问题,或者更好的是,知道它为什么会坏?任何人,这是代码:

#pragma once
#include <typeinfo>
#include <vector>

class ParamChecker
{
public:
    typedef std::vector<const type_info*> Types;

    template <typename T> void PushType()
    {
        types.push_back(&typeid(T));
    }

    template <typename Head, typename... Tail> void PushTypes()
    {
        PushType<Head>();
        PushTypes<Tail...>();
    }
    void PushTypes() {}

private:
    Types types;
};

提前致谢!

【问题讨论】:

  • 你用的是什么编译器?
  • Visual Studio 2013,不太确定确切的版本。
  • 什么意思,破坏编译器?编译器会崩溃吗?
  • 总是复制并粘贴错误消息并发布它们,以便其他人看到它们与您看到的完全一样。

标签: visual-studio templates c++11 rtti variadic


【解决方案1】:

我没有要测试的 Visual Studio,但我在你的代码中看到了问题,所以我会告诉你,你可以在 Visual Studio 上测试。

问题是,当你递归到PushTypes&lt;Tail...&gt;(); 并且Tail... 为空时,你调用的是PushTypes&lt;&gt;();。请注意,您的基本情况 void PushTypes() {} 不是模板函数,即您不能通过 PushTypes&lt;&gt;(); 调用它。

另外请注意,您需要一个类模板作为助手,因为我们还没有针对函数模板的部分特化(希望很快就会推出)。

但这是你可以做的。

#include <typeinfo>
#include <vector>

class ParamChecker {
  public:

  /* Our type info structure. */
  using Types = std::vector<const std::type_info *>;

  /* Delegate work to PushTypesImpl<>. */
  template <typename... Types>
  void PushTypes() {
    PushTypesImpl<Types...>()(types_);
  }

  private:

  /* Forward declaration. */
  template <typename... Types>
  class PushTypesImpl;

  /* Collection of type information. */
  Types types_;

};  // ParamChecker

/* Base case. */
template <>
class ParamChecker::PushTypesImpl<> {
  public:

  void operator()(Types &) const { /* Do nothing. */ }

};

/* Recursive case. */
template <typename Head, typename... Tail>
class ParamChecker::PushTypesImpl<Head, Tail...> {
  public:

  void operator()(Types &types) const {
    types.push_back(&typeid(Head));
    PushTypesImpl<Tail...>()(types);
  }

};

int main() {
  ParamChecker x;
  x.PushTypes<>();  // push nothing.
  x.PushTypes<int>();  // push int.
  x.PushTypes<int, double>();  // push int and double.
}

编辑: 以下是使用type_list 并将其作为参数传递的替代方法。

注意:这里使用type_list&lt;&gt;而不是tuple&lt;&gt;是因为构造一个空元组需要所有类型都是默认可构造的,即使它们都是默认可构造的,我们不想无缘无故地默认构造它们。

template <typename... Types>
class type_list {};

class ParamChecker {
  public:

  /* Our type info structure. */
  using Types = std::vector<const std::type_info *>;

  /* Base case. Do nothing. */
  void PushTypes(type_list<> &&) {}

  /* Recursive case. */
  template <typename Head, typename... Tail>
  void PushTypes(type_list<Head, Tail...> &&) {
    types_.push_back(&typeid(Head));
    PushTypes(type_list<Tail...>());
  }

  private:

  /* Collection of type information. */
  Types types_;

};  // ParamChecker

int main() {
  ParamChecker x;
  x.PushTypes(type_list<>());  // push nothing.
  x.PushTypes(type_list<int>());  // push int.
  x.PushTypes(type_list<int, double>());  // push int and double.
}

【讨论】:

  • 嗯...感谢您的意见。我已经在元组的帮助下运行了一些东西,但我仍然会尝试解决这个问题。不过我今天无法访问我的电脑,所以我必须等到明天:/
  • 您是否让PushTypes 函数将元组作为参数?
  • 是的。这样参数包被包含并且更容易使用。另外,由于它被包含,编译器不会混淆。
  • 我猜您的解决方案看起来像 void PushTypes(std::tuple&lt;&gt; &amp;&amp;); 和 void PushTypes(std::tuple&lt;Head, Tail...&gt; &amp;&amp;);,呼叫站点看起来像:PushTypes(std::tuple&lt;int, double&gt;());。我个人认为PushTypes&lt;int, double&gt;() 是一个更干净的接口,即使实现更丑陋,我通常更喜欢调用站点是干净的。但是,如果您决定仍然支持tuple 方法,那么请考虑改用type_list。
  • 编辑答案以提供替代解决方案。
猜你喜欢
  • 2021-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-02
  • 2018-03-25
  • 1970-01-01
  • 2021-02-01
相关资源
最近更新 更多