【问题标题】:Can I extract C++ template arguments out of a template class?我可以从模板类中提取 C++ 模板参数吗?
【发布时间】:2009-11-19 16:38:07
【问题描述】:

基本上,给定一个这样的模板类:

template< class Value > class Holder { }; 

我希望能够发现给定 Holder 类的类型 Value。我认为我可以制作一个带有模板模板参数的简单元函数,如下所示:

template< template< class Value > class Holder > class GetValue
{
    typedef Value Value;
};

然后像这样提取出Value类型:

GetValue< Holder< int > >::Value value;

但相反,我只收到一条指向元函数声明的错误消息:

error: ‘Value’ does not name a type

有没有办法完成这种事情?谢谢。

[编辑] 我也收到错误消息:

error: type/value mismatch at argument 1 in template parameter list for ‘template<template<class Value> class Holder> class GetValue’
error:   expected a class template, got ‘Holder<int>’

这让我得出结论,Phil Nash 是正确的,您不能将类作为模板模板参数传递。

【问题讨论】:

    标签: c++ templates metaprogramming


    【解决方案1】:

    你为什么不简单地将你的持有者类更改为

    template< class Value > class Holder {
        typedef Value value_type;
    
        value_type m_val; // member variable
    };
    

    在任何使用 Holder 类型对象的方法中,您都可以像这样访问包含的类型:

    template< class THolder >
    void SomeMethod( THolder const& holder ) {
         typename THolder::value_type v = holder.m_val;
    }
    

    这种方法遵循所有 STL 类使用的模式,例如,std::vector::value_type 是 int。

    我认为您正在尝试进行部分模板专业化:

    template<class T>
    class GetValue {
    };
    
    template<class Value>
    class GetValue< Holder<Value> > {
    public:
        typedef Value value_type;
    };
    

    在您的代码中,您可以执行以下操作:

    template<class THolder>
    void SomeMethod( THolder const& h ) {
        typename GetValue< THolder >::value_type v = h.m_v;
    }
    

    不过,总的来说,我更喜欢第一种解决方案。

    【讨论】:

    • 并非总是可以做到这一点。我之前肯定需要外化形式
    • 我使用部分模板特化添加了一个外部表单。
    • 你当然是对的。您可以使用 boost 样式的外部表单来定义例如使用相同的偏特化方法的数组的 value_type。
    • 部分模板专业化对我来说是正确的方法。谢谢!
    • @drpepper:这就是 C++ 中的元编程。通过部分专业化,还应该可以使其更加通用(如您的示例):template &lt;class T, template &lt;class&gt; class Holder&gt; struct GetType&lt;Holder&lt;T&gt; &gt;{ typedef T type; };
    【解决方案2】:
    template <class T> void extract_type(Holder<T>)
    {
        printf("%s\n", typeid(T).name());
    }
    

    我假设您想在非模板函数中使用它。这有点困难:

    template <class T> class GetValue;
    template <class T> class GetValue<Holder<T> >
    {
    public:
        typedef T value_type;
    };
    

    神奇的谷歌词是“部分模板专业化”

    【讨论】:

      【解决方案3】:

      我认为您需要在某处输入类型名。

      [编辑] 该死,我只是想检查一下我是否怀疑它需要在 GetValue 之前,但 Mykola 最先到达那里 :-)

      问题在于 Value 是一个依赖类型。编译器不知道它是用来命名类型还是值,因此您需要提供提示。

      [编辑2]

      哎呀。试图回答太快有问题。 我错过了您试图使用模板模板来实现这一点的事实。 允许你做的是传递一个 template 而不是 type。在这种情况下,您可以传递一个 Holder。但这对您没有帮助,因为您想传递一个类型 Holder

      看起来 Mykola 也意识到了这一点并删除了他的答案。

      您需要为此使用部分模板专业化。在我有机会完成我自己的示例之前,Sebastian 已经击败了我 :-)

      【讨论】:

      • 你们太快了!我不能在这里打错字;)但错字不是真正的问题。
      • 你确定吗?您能否更新您的原始问题以反映您的更改以确保我们在同一页面上?
      • 我认为你是对的,缺少 typename 似乎是问题所在。 @drepper:如果没有,请发布更新的代码。
      • @naveen 我添加了一个 typedef 但它没有任何区别
      • @drpepper typename,你的意思是? - 无论如何,真正的问题是模板模板
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多