【问题标题】:How to name a nested template in a templated base class?如何在模板化基类中命名嵌套模板?
【发布时间】:2012-05-25 07:47:04
【问题描述】:

在下面的设置中,我怎样才能使我可以在派生类Derived<T>中引用名称Bar

template <typename T> struct Foo
{
    template <typename U> struct Bar { };
};

template <typename T> struct Derived : Foo<T>
{
    // what goes here?

    Bar<int> x;  // Error: 'Bar' does not name a type
};

我试过using Foo&lt;T&gt;::Bar;,但这没有帮助。是否有任何类型的 using 声明可以使派生类知道嵌套基模板的名称,以便我可以保留简单的声明 Bar&lt;int&gt; x

我知道我可以说typename Foo&lt;T&gt;::template Bar&lt;int&gt; x;,但我有很多这样的情况,我不想用这么多冗长不必要地给代码增加负担。我也有很多不同的“ints”,所以每个嵌套模板实例的typedef 也不可行。

另外,我现在不能使用 GCC 4.7 也不能使用 C++11,因此我想要一个没有模板别名的“传统”解决方案。

【问题讨论】:

    标签: c++ templates base-class name-lookup


    【解决方案1】:

    在 C++11 中,您可以使用别名模板:

    template <typename T> struct Derived : Foo<T>
    {
      template<typename X> using Bar = typename Foo<T>::template Bar<X>;
      Bar<int> x;
    };
    

    编辑

    传统的解决方案就是你已经说过的typename Foo&lt;T&gt;:template Bar&lt;int&gt;,或者模拟“模板类型定义”

    template <typename T> struct Derived : Foo<T>
    {
      template<typename X>
        struct Bar
        { typedef typename Foo<T>::template Bar<X> type; };
      typename Bar<int>::type x;
    };
    

    在语言中添加别名模板的原因之一是它们支持在 C++03 中无法轻松表达的东西

    【讨论】:

    • 是的,这是真的。不幸的是,我无法实际使用这样的编译器,所以如果可能的话,我想要一个“传统”的解决方案:-S
    • @KerrekSB:它有什么“非传统”?
    • @Nawaz:我不能在需要这个的项目中使用它:-)
    【解决方案2】:

    x 声明为Foo&lt;T&gt;::Bar&lt;int&gt; x; 对我很有效。

    【讨论】:

    • 我认为,这不应该工作!如果是这样,那么我想知道为什么会这样。也许,编译器有错误?
    • @Nawaz:为什么?它在 Dev-C++ 4.9.9.2 中编译。
    • 我不想更改声明。我真的想要能够说Bar&lt;int&gt; x;
    • miloszmaki: Bar 是一个依赖类型,所以如果没有typename,它就不能工作。
    • @miloszmaki :那不是编译器,它是一个(糟糕的)IDE,捆绑了一个彻头彻尾的古老编译器(GCC 3.4.2)。
    【解决方案3】:

    这行得通:

    template <typename T> struct Foo
    {
        template <typename U> struct Bar { };
    };
    
    template <typename T> struct Derived : Foo<T>
    {
        template<class W>
        struct Bar : public Foo<T>::template Bar<W> {
    
        };
    
        Bar<int> x;  
    };
    

    IDK 如果这是您正在寻找的,但它确实可以编译。

    【讨论】:

    • 这不完全一样。它很接近,但如果类型相同,即使是微不足道的事情也不会在这种情况下:Derived&lt;int&gt; d; Foo&lt;int&gt;::Bar&lt;int&gt; y; d.x = y;
    • 这在我的回答中给出了比“模板 typedef”更好的语法,但值得注意的是 Foo&lt;T&gt;::Bar&lt;int&gt;Derived&lt;T&gt;::Bar&lt;int&gt; 实际上不是同一类型。这可能无关紧要,但在某些情况下它可以做到,例如与Foo::Bar 一起使用的模板或重载可能与Derived::Bar 不匹配,因此使用了错误的重载。 (编辑:我看到 cvoinescu 说了同样的话,但更清楚。)
    • @cvoinescu 是的,在这种情况下它不起作用。但是,如果该类仅在Derived 内部使用,那么它将起作用(尽管我不知道是否是这种情况)。我只是想指出一种比用于声明模板 typedef 的语法更短的语法。
    猜你喜欢
    • 2018-11-26
    • 2022-07-19
    • 2016-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多