【问题标题】:Template template non-type parameter模板模板非类型参数
【发布时间】:2016-06-23 17:56:25
【问题描述】:

我不太确定 C++ 中是否有这样的功能,如果有的话,我似乎无法让它工作,所以我决定问一下。我可以有一个模板模板非类型参数。像这样的:

template<template<int> class A, int num>
class C
{
private:
     A<num> obj;
};

我的主要问题是我想要一个 C 类,它接受 2 个类作为模板参数。这两个类都专门针对一个非类型参数——比如 A、B,我想将它们传递给 C 类,它接受两个类作为模板参数。但是,我需要确保这两个类都专门针对相同的非类型参数 - 例如 A、B 不应被允许作为 C 类的参数。

【问题讨论】:

  • 是的,有可能

标签: c++ templates non-type


【解决方案1】:

类似的方法是这样做:

template<int I>
class A {};

template<int I>
class B {};

// Forward declaration.
template<typename T, typename U>
class C;

template<template<int> class TA, template<int> class TB, int I, int J>
class C<TA<I>, TB<J>> {
    // J exists only to make sure integer parameters match.
    static_assert((I == J), "Template parameters' integer parameters are mismatched.");

  private:
    TA<I> objA;
    TB<I> objB;

  public:
    // ...
};

// ...

C<A<4>, B<4>> ca4b4;   // Valid.
C<A<4>, B<16>> ca4b16; // Static assert fails.

这将允许您保证两个容器具有相同的整数参数,如果它们没有,则发出可读的错误消息。



编辑:请注意,如果您不使用两个单独的整数参数并手动检查是否相等,则尝试使用不匹配的模板模板参数创建实例将发出难以理解的“不完整类型”错误消息。

template<template<int> class TA, template<int> class TB, int I>
class C<TA<I>, TB<I>> {
    // ...
};

// ...

C<A<4>, B<16>> ca4b16; // Oops.
/* Error messages:
 * GCC:
 *   error: aggregate 'C<A<4>, B<16> > ca4b16' has incomplete type and cannot be defined
 *      C<A<4>, B<16>> ca4b16;
 *                     ^
 * MSVC:
 *   error C2079: 'ca4b16' uses undefined class 'C<T, U>'
 *      with
 *      [
 *          T=A<4>,
 *          U=B<16>
 *      ]
 */

这是因为实际定义只能捕获两个参数具有相同整数参数的实例,并且任何使用不匹配整数参数的情况都将退回到前向声明,这是不完整的。使用两个单独的整数参数,然后手动检查是否相等,可以让我们捕获错误的实例化,而不是让它们退回到声明中,因此我们可以将通用错误转换为实际告诉您问题所在的内容。

【讨论】:

    【解决方案2】:

    您可能希望使用“makeC”来简化您的代码:

    #include <iostream>
    
    template <template<int> class A, template<int> class B, int N>
    class C {
        A<N> a;
        B<N> b;
    };
    
    using namespace std;
    
    template <template<int> class A, template<int> class B, int N>
    C<A,B,N> makeC(A<N> a, B<N> b) {
        return C<A, B, N>{};
    }
    
    template<int N>
    class AImpl {
    
    };
    
    template<int N>
    class BImpl {
    
    };
    
    
    int main() {
        auto c = makeC(AImpl<2>{}, BImpl<2>{});
        //auto error = makeC(AImpl<1>{}, BImpl<2>{});
    
        return 0;
    }
    

    【讨论】:

    • 说 AImpl 类需要更多模板参数,例如 ,有没有办法从 C 类中隐藏模板类参数?像 AImpl 之类的东西(基本上 C 类不需要知道 aboutSomeClass 但需要知道 5.
    • A 和 B 之间的 SomeClass 是否必须相同?
    • 不是真的,我只是想在 C 类中隐藏它。基本上而不是 template&lt;template&lt;class,int&gt; class A, class SomeClass, int num&gt; 我想要像 template&lt;template&lt;int&gt; class A_speicalized_by_first_parameter, int num&gt; 这样的东西
    【解决方案3】:

    我的错,经过一番修补后,我设法说对了。问题是我打电话给C&lt;A&lt;5&gt;&gt;,显然我需要打电话给C&lt;A, 5&gt;。下面是一个例子,说明我是如何让整个事情发挥作用的,以防万一有人需要它:

    template<int a, int b, int c>
    class Anac
    {
    public:
        void print()
        {
            std::cout << "Anac: " << a << " " << b << " " << c << "\n";
        }
    };
    template<int a, int b, int c>
    
    class Mamut
    {
    public:
        void print()
        {
            std::cout << "Mamut: " << a << " " << b << " " << c << "\n";
        }
    };
    
    template <class C>
    class R
    {
    
    };
    
    template< template<int, int, int> class A, template<int, int, int> class B, int a, int b, int c>
    class gm
    {
    private:
        A<a,b,c> p1;
        B<a,b,c> p2;
    public:
        void print()
        {
            p1.print();
            p2.print();
        }
    };
    int main()
    {
        gm<Anac, Mamut, 3, 4, 5> game;
        game.print();
        std::cin.ignore();
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2021-03-18
      • 1970-01-01
      • 1970-01-01
      • 2011-08-06
      • 2014-10-03
      • 1970-01-01
      相关资源
      最近更新 更多