模板模板非类型参数

时间:2016-06-23 17:56:26

标签: c++ templates non-type

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

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

我的主要问题是我希望有一个C类接受2个类作为模板参数。这两个类都专注于非类型参数 - 例如A&lt; 5&gt;,B&lt; 5&gt;。我想将它们传递给C类,它接受两个类作为模板参数。然而,我需要确保这两个类都专用于相同的非类型参数 - 例如A&lt; 3&gt;,B&lt; 4&gt;。不应该被允许作为C类的参数。

3 个答案:

答案 0 :(得分:1)

我的不好,经过一些修修补补后,我设法称之为正确。问题是我在呼叫C<A<5>>,我显然需要呼叫C<A, 5>。这是一个例子,说明如果有人需要它,我是如何使整个事情发挥作用的:

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;
}

答案 1 :(得分:1)

您可能希望使用“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;
}

答案 2 :(得分: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>
 *      ]
 */

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