Template template non-type parameter

℡╲_俬逩灬. 提交于 2021-01-28 18:03:32

问题


I am not really sure if there's such a feature in C++, and if there is I can't seem to make it work, so I decided to ask. Can I have a template template non-type parameter. Something like this:

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

My main issue is that I want to have a class C that accepts 2 classes as template parameters. Both of these classes specialize over a non-type parameter - say A<5>, B<5> and I want to pass them to class C which accepts two classes as template parameters. I need to make sure however that both of these classes specialize over the same non-type parameter - for example A<3>, B<4> shouldn't be allowed as arguments to class C.


回答1:


You may want to simplify your code with a "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:


A similar approach would be to do something like this:

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.

This will allow you to guarantee that both containers have the same integer parameter, and emit a readable error message if they don't.



Edit: Note that if you don't use two separate integer parameters and manually check for equality, attempting to create an instance with mismatching template template parameters will give off a less understandable "incomplete type" error message.

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>
 *      ]
 */

This is because the actual definition will only be able to catch instances where both parameters have the same integer parameter, and any usage with mismatching integer parameters will instead fall back on the forward declaration, which is incomplete. Using two separate integer parameters, then manually checking for equality, allows us to catch bad instantiations instead of letting them fall back on the declaration, so we can convert that generic error into something that actually tells you what the problem is.




回答3:


My bad, after some tinkering I managed to call it right. The issue was I was calling C<A<5>> and i needed to obviously call C<A, 5>. Here's an example of how I made the whole thing work just in case if anybody ever needs it:

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


来源:https://stackoverflow.com/questions/37998655/template-template-non-type-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!