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?
source to share
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>;
};
source to share