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 ofS
. - 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 &) { /* ... */ }