【问题标题】:How to declare/define a class with template template parameters without using an extra template parameter如何在不使用额外模板参数的情况下使用模板模板参数声明/定义类
【发布时间】:2008-11-24 13:41:58
【问题描述】:

考虑以下使用模板模板参数...

#include <iostream>

template <typename X>
class A
{
    X _t;
public:
    A(X t)
        :_t(t)
    {
    }
    X GetValue()
    {
        return _t;
    }
};

template <typename T, template <typename T> class C >
class B
{
    C<T> _c;
public:
    B(T t)
        :_c(t)
    {
    }
    T GetValue()
    {
        return _c.GetValue();
    }
};

using namespace std;

int main()
{
    B<int, A> b(10);
    cout<<b.GetValue();
    return 0;
}

有没有什么方法可以去掉模板参数T?例如有没有办法使以下工作?

//Does not compile
template <template <typename T> class C >
class B
{
    C _c;
public:
    B(T t)
        :_c(t)
    {
    }
    T GetValue()
    {
        return _c.GetValue();
    }
};

int main()
{
    B< A<int> > b(10);
    cout<<b.GetValue();
    return 0;
}

【问题讨论】:

    标签: c++ templates metaprogramming


    【解决方案1】:

    我假设您在代码中关注 X 和 A。

    通常的模式是有

    template<typename C>
    struct B
    {
       C c;
    };
    

    然后,在符合替换条件的类内部:

    template<typename X>
    class A
    {
       typedef X type_name;
       X t;
    };
    

    然后你可以使用C::type_name访问模板参数。

    【讨论】:

    • 感谢您的回答,尽管我最终自己发现了这一点。我正在编辑问题并发布我的工作,但显然我来对地方了!
    • 请注意,Sunlight 的回答比我的要好,因为他明白你想要什么。无需像我向您展示的那样重新绑定。仅当您使用 A 时才需要,但偶尔需要 A。或者如果用户的视图是 A,但你使用 A .
    • +1!我正在寻找一种方法来接收对任何标准容器的引用,并且使用这种方式获取带有C::value_type 的类型非常有用。谢谢!
    【解决方案2】:

    这是不可能的。请注意,这是一个常见的误解:A&lt;int&gt; 不再是类模板!所以它不适合模板模板参数,但必须使用类型参数来接受:

    template<typename C>
    struct B {
        C c;
    };
    
    B< A<int> > b;
    

    你使用单独参数的方式没问题。

    如果您想接受A&lt;int&gt; 但又想将其重新绑定到另一个参数,您可以使用此模式,标准分配器也使用此模式:

    template<typename T>
    struct A {
        template<typename U>
        struct rebind {
            typedef A<U> type;
        };
    };
    
    template<typename C>
    struct B {
        typename C::template rebind<float>::type c;
    };
    
    B< A<int> > b;
    

    现在,B&lt; A&lt;int&gt; &gt;::c 的类型为 A&lt;float&gt;C:: 之前的 typename 告诉编译器末尾的 ::type 是类型而不是静态非类型成员。 C:: 之后的 template 告诉编译器 rebind&lt;float&gt; 是模板实例化,而不是比较。

    【讨论】:

    • 好酷!不错的答案,但不幸的是只有一个答案,我认为@sunlight 早些时候向您发布了他的解决方案。我赞成你的回答。
    【解决方案3】:

    有什么问题:

    template <typename C >
    struct B
    {
        C c;
    };
    
    int main()
    {
        B< A<int> > b;
        return 0;
    }
    

    【讨论】:

    • 我的错,问题没有完全说明。现在是。
    【解决方案4】:

    您可以嵌套参数。也就是说,参数的值本身可以被参数化。

    template <typename X>
    struct A
    {
      X t;
    };
    
    template <typename  C>
    struct B
    {
      C c;
    };
    
    int main()
    {
      B< A<int> > b;
      return 0;
    }
    

    在此示例中,main() 中的 b 声明使用 int 作为参数创建了 A 的特化,然后使用 A&lt;int&gt; 作为参数创建了 B 的特化。因此,在B 的特化中,CA&lt;int&gt;

    【讨论】:

    • 根据原始问题,您的解决方案是正确的,但我添加了一些我第一次错过的细节。谢谢。
    猜你喜欢
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 2019-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多