Adrian
Adrian

Reputation: 10911

How to have a template template parameter take a numeric value?

I want to have a template parameter accept a template that has a numeric template argument.

This example maybe overly simplified, but I'd like something like this:

template <int X>
struct XX
{
  static const int x = X;
};

template<typename TT, TT V, template<V> TX>
void fnx(TX<V> x)
{
  static_assert(V == TX::x, "IMPOSSIBLE!");
}

void fny()
{
  fnx(XX<1>())
}

I must not be understanding the syntax for this, as it must be possible. How would I accomplish this?

Upvotes: 6

Views: 213

Answers (2)

Barry
Barry

Reputation: 303127

Just fixing up your syntax a bit - since the template template parameter is improperly specified, we'd end up with something like this:

template <typename T, template <T > class Z, T Value>
//                    ^^^^^^^^^^^^^^^^^^^^^
void foo(Z<Value> x) { }

However, the compiler can't deduce T here - it's a non-deduced context. You'd have to explicitly provide it:

foo<int>(XX<1>{});

That's pretty annoying. I cannot even write a type trait such that non_type_t<XX<1>> is int (where that type trait does actual introspection on the type, not something that trivially returns int).


There is a proposal to improve this process (P0127) by amending the non-deduced context-ness of non-type template arguments.

Upvotes: 6

Alan Stokes
Alan Stokes

Reputation: 18964

Your declaration of fnx needs some work, and the type TT can't be deduced at the call site.

template<typename TT, TT V, template<TT> class TX>
void fnx(TX<V> x)
{
  static_assert(V == TX<V>::x, "IMPOSSIBLE!");
}

void fny()
{
  fnx<int>(XX<1>());
}

Working example: https://ideone.com/57PsCA

Upvotes: 2

Related Questions