I have a templated struct like this:
template<int Min, int Max>
struct TInt
{
int Get() const { return StoredVal; }
TInt& operator=(int Val) { StoredVal = FMath::Clamp(Val, Min, Max); return *this; }
bool WithinRange(int Val) const { return Min <= Val && Val <= Max; }
private:
int StoredVal = Min;
};
And after reading this proposal tried to create these templates to check if a type is a template specialization of TInt
:
template<class T, template<class...> class Primary>
struct is_specialization_of : std::false_type {};
template<template<class...> class Primary, class... Args>
struct is_specialization_of<Primary<Args...>, Primary> : std::true_type {};
template<class T, template<class...> class Primary>
inline constexpr bool is_specialization_of_v = is_specialization_of<T, Primary>::value;
This is how I try to use it:
template<typename T>
struct IsValidType { static constexpr bool Value = is_specialization_of<T, TInt>; };
But I keep getting this error: "Cannot substitute template argument TInt for template template parameter Primary"
. I have checked and tried other answers to similar questions here on SO, but nothing really seems to work for me.
I don't really care about the general case (variadic template), just two template parameters which would also increase my learning if I could do exactly that.
What do I need to do to make this work?
The problem is:
template<class T, template<class...> class Primary>
struct is_specialization_of : std::false_type {};
is_specialization_of
takes something of the form template <class...> class Primary
. A class template that accepts some number of type template parameters. But TInt
doesn't accept type template parameters, it accepts non-type template parameters (specifically two int
s). There's no way in C++ today to write is_specialization_of
properly.
But if you just want to write a specific trait to check if something is a TInt
, that's much more straightforward with a variable template:
template <class T>
inline constexpr bool is_tint = false;
template <int Min, int Max>
inline constexpr bool is_tint<TInt<Min, Max>> = true;
or shoved onto "one line" (ish) with a requires expression:
template <class T>
concept is_tint = requires (T const& t){
[]<int Min, int Max>(TInt<Min, Max> const&){}(t);
};