【问题标题】:difference in 2 template dependent typename kinds2 种依赖于模板的类型名种类的区别
【发布时间】:2017-09-08 08:58:54
【问题描述】:

在 Scott Meyers 的书中,模板中依赖于模板参数的名称称为依赖名称。 (当依赖名嵌套在类中时,我称之为嵌套依赖名)

所以必须在依赖名称前使用“typename”关键字,对吧?

template<typename C>
void print2nd(const C& container) {
typename C::const_iterator iter(container.begin()); 
...
}

但是为什么在这段取自 Josuttis 书中的代码中,std::vector 是另一个模板的实例化,显然依赖于 T,他们在这里不使用“typename”:

template <typename T>
class Stack {
    (?typename?) std::vector<T> elems;
...
};

这一切看起来都令人困惑,尤其是 Meyers 的另一个例子:

template<typename IterT> 
void workWithIterator(IterT iter) {
    typename std::iterator_traits<IterT>::value_type temp(*iter);
... }

在我看来,它们都一样。怎么区分?

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    在第一个示例 (typename C::const_iterator) 中,const_iterator 无法直接为编译器所知:例如,它可能是静态成员。这就是为什么你需要在声明前加上typename,以表明它是一个类型。

    在第二个例子中,编译器知道std::vector&lt;T&gt; 是一个类型,即使不知道T 是什么。这就是为什么在这种情况下不需要typename

    【讨论】:

    • 你怎么知道,C::const_iterator 是不可知的?是因为它嵌套到未知类​​型 C 吗?然后,这是 Meyers 的另一个示例: template void workWithIterator(IterT iter) { typename std::iterator_traits::value_type temp(*iter); ... }
    • @barney 是的,因为它嵌套在C 中,所以编译器此时很难确定const_iterator 是什么。如前所述,您可以将static int const_iterator 嵌套在C 中,这是一个名为const_iterator 的静态成员,类型为int,而不是类型。但是在这种情况下,前缀typename 意味着“const_iterator 是一个类型名称”。但是,std::vector&lt;&gt; 是一个类型(它采用模板参数),编译器知道这一点,因此编译器在不知道 C 的确切类型的情况下计算出这一点。
    • @barney 对于您提到的另一个示例 (std::iterator_traits&lt;IterT&gt;::value_type):iterator_traits 被称为类型,但编译器不知道特定的 iterator_traits&lt;IterT&gt; 实现中的内容(因为类可以专门用于IterT) 后面的类型,因此您需要使用typename 来表示您引用了一个类型,就像C::const_iterator 示例一样。
    【解决方案2】:

    当你有

    typename C::const_iterator iter(container.begin()); 
    

    const_iterator 部分的类型取决于C 是什么。所以你需要typename 告诉编译器C::const_iterator 是一个类型。

    std::vector<T> elems;
    

    您正在声明一个std::vector,其元素的类型为T。你根本不需要typename。尽管 vector 取决于 类型 T 它不是依赖于 T 是什么的名称。

    您可以在Where and why do I have to put the "template" and "typename" keywords? 阅读更多关于何时何地需要typenametemplate

    【讨论】:

    • 我正在努力获得差异:) 因此,当编译器看到“C::const_iterator”在将 C 实例化/替换为任何具体类型之前它是未知的时,“const_iterator”是什么,对吧?但是“std::vector”也取决于确切的具体T,或者不是?仅仅因为它是实例化?
    • Meyers 的另一个例子是指类似于 vector 但仍然带有“typename”关键字的东西: template void workWithIterator(IterT iter) { typename std::iterator_traits: :value_type temp(*iter); ... } 为什么在这里? iterator_traits 和 vector 有什么区别?
    • @barney 当编译器看到some_name::some_other_name 时,它不希望看到some_name 是模板类型时的类型。所以你使用typename 来告诉它是一个名字而不是它假设的一个非名字。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-08
    • 2018-05-09
    • 2013-03-03
    • 1970-01-01
    • 2019-08-20
    相关资源
    最近更新 更多