Compiletime checks if there are two template instances with the same template parameter

If I have two unrelated patterns A

and B

how do I do a match check to see if there are two identical parameters. For example. if I have some parameter type P1

and P2

, I want the client to instantiate A<P1>

and B<P2>

, but not A<P1>

and B<P1>

.

I have a solution to this using a variational template Checker<typename... Xx>

to be installed with the appropriate templates:

using a = A<P1>;
using b = B<P1>;
using checker = Checker<a, b>;

checker::init(); // can be empty
                 // static_assert fails here

      

This works if each parameter type has a unique identifier (mask) and so I can OR all the masks and see if the number of ones is the same as the size of the parameter packet Checker

.

This solution is not good because the client might forget to install the template Checker

.

I wonder if this check could be done somewhat under the hood?

+3


source to share


1 answer


This solution is not good because the client might forget to install the template Checker

.

Good intuition - so you need to prevent the client to create instances A

and B

to create an instance Checker

. You can achieve this by giving them type aliases that are only available with Checker

.

namespace detail
{
    template <typename T> struct A;
    template <typename T> struct B;
}

template <typename P0, typename P1>
struct Checker
{
    static_assert(!std::is_same_v<P0, P1>);

    using A = detail::A<P0>;
    using B = detail::B<P1>;
};

      

Using:

using ClientABProvider = ABProvider<foo, bar>;
using A = typename ClientABProvider::A;
using B = typename ClientABProvider::B;

      



using ClientABProvider = ABProvider<foo, foo>; // Error!
using A = typename ClientABProvider::A;
using B = typename ClientABProvider::B;

      


If you want A

and B

be user supplied, you can have templates of the Checker

type template type, but this kind defeats its purpose since the user already has access to A

and B

in the first place.

template <typename P0, typename P1>
struct Checker
{
    static_assert(!std::is_same_v<P0, P1>);

    template <template <typename> class XA>
    using A = XA<P0>;

    template <template <typename> class XB>
    using B = XB<P1>;
};

      

+2


source







All Articles