Home > front end >  Infer type of non-type template argument
Infer type of non-type template argument

Time:04-23

I'm not great at template metaprogramming, so apologies if this is a dumb question.

I have a type like

template<int n>
struct S
{
  typedef decltype(n) type_of_n;

  // ...
};

and I'd like to write functions that look something like

template<
  typename T, 
  typename T::type_of_n n,
  typename = std::enable_if_t<std::is_same<T, S<n>>::value>>
void f(const T &) { /* ... */ }

with the idea being that if the type of the non-type template argument to S changes at some point in the future (say to std::size_t or int64_t or something) then calling code will just continue working. But I'm not sure how to get the compiler to infer both T and n in tandem here.

The only things I've come up with are basically hacks:

  • Do something like typedef int type_of_S_n outside of S.
  • Write something like S<0>::type_of_n instead of actually inferring the type

Is what I'm trying to do possible? If not, is there a "cleaner" way to do it than the hacks above?

CodePudding user response:

If you are looking to only accepts S and want to also deduce the value of n, then you can since c 17 use auto to deduce the type of a non-type template parameter.

template<auto n>
void f(const S<n> &) { /* ... */ }

You can also make it more generic and accept any type with a single non-type parameter by using a template template parameter.

template<template <auto> typename T, auto n>
void f(const T<n> &) { /* ... */ }

CodePudding user response:

if the type of the non-type template argument to S changes at some point in the future (say to std::size_t or int64_t or something) then calling code will just continue working.

You can use the placeholder type auto with C 17 as shown below:

template<auto n>  //note the auto here
struct S
{
  typedef decltype(n) type_of_n;

  // ...
};

CodePudding user response:

You can do a traits to know if a type is a S<n>:

template <typename T>
struct is_a_S : std::false_type {};

template <int N>
struct is_a_S<S<N>> : std::true_type {};

Then your SFINAE can be done like that:

template<
  typename T, 
  std::enable_if_t<is_a_S<T>::value, int> = 0>
void f(const T &) { /* ... */ }

CodePudding user response:

C 20 concepts make things easier

#include <concepts>

template<int n>
struct S {
  typedef decltype(n) type_of_n;
};

template<class T>
  requires std::same_as<T, S<typename T::type_of_n{}>>
void f(const T &) { /* ... */ }

Demo

  • Related