Search code examples
c++templatestemplate-meta-programming

Template by nested structs in C++


I would like to write this code, but it produces an error.

template<int N>
struct A {
    struct B {

    };
    B f() { return B{}; }
};

template<typename T>
constexpr bool val = false;

template<int N>
constexpr bool val<typename A<N>::B> = true;
error: template parameters not deducible in partial specialization:
   13 | constexpr bool val<typename A<N>::B> = true;

While this code is working perfectly

template<int N> struct A;

template<int N>
struct AB {

};

template<int N>
struct A {
    AB<N> f() { return AB<N>{}; }
};

template<typename T>
constexpr bool val = false;

template<int N>
constexpr bool val<AB<N>> = true;

I understood that C++ would have to check if there exists a N such that T equals A<N>::B when evaluating val<T> which is too difficult. That's why there is an error. But my question is: Is there any way of keeping the struct B inside A and defining the value val<A<N>::B> for every N?

I understand the error if B was defined as a reference to a struct outside A (for instance using B = int;) but if B is a struct defined inside A then there is no ambiguity and N is easily deduced.


Solution

  • If you provide way to retrieve template parameters of A from B, you might do it by SFINAE/constraint:

    template<int N>
    struct A {
        struct B {
            constexpr static int value = N;
        };
    };
    
    template <typename T>
    constexpr bool val = false;
    
    template <typename T>
    requires (std::is_same_v<typename A<T::value>::B, T>) // C++20
    constexpr bool val<T> = true;
    

    Demo