I have a class that acts as a type trait, returning whether a certain condition is true. It's intended to mark classes as supporting a particular feature.
template <typename T> struct Check : std::false_type { };
I have a template class that contains an inner class:
template <unsigned N>
struct Kitty
{
struct Purr;
};
I want to mark the inner class Purr
as supporting the feature denoted as Check
. In other words, I want to make it so that Check<Kitty<123>::Purr>::value
is true
. I tried doing the following, but I get an error:
template <unsigned X>
struct Check<typename Kitty<X>::Purr> : std::true_type { };
error: template parameters not deducible in partial specialization:
Is it possible to accomplish this, or is it a limitation of C++ that you can't specialize on inner template class members?
As outlined in my comment, it is possible to make this a deduced context by using a base class, which I'll call KittyBase
. Using a base class is actually common for templates, to avoid having unnecessary code duplicated for every new instantiation. We can use the same technique to get Purr
without needing to deduce N
.
However, simply putting Purr
in the base class will remove its access to N
. Fortunately, even in making Purr
itself a template, this can still be a non-deduced context: Live example
#include <type_traits>
template <typename T> struct Check : std::false_type { };
struct KittyBase
{
template<unsigned N> // Template if Purr needs N.
struct Purr;
protected:
~KittyBase() = default; // Protects against invalid polymorphism.
};
template <unsigned N>
struct Kitty : private KittyBase
{
using Purr = KittyBase::Purr<N>; // Convenience if Purr needs N.
Purr* meow;
};
template <unsigned X>
struct Check<typename KittyBase::Purr<X>> : std::true_type { };
static_assert(not Check<int>{});
static_assert(Check<Kitty<123>::Purr>{});
static_assert(Check<Kitty<0>::Purr>{});
int main() {}
If you wish, you can even make KittyBase::Purr
private and use template<typename T> friend struct Check;
to grant access to the trait. Unfortunately, I don't know whether you can limit that to only certain specializations of the trait.