I have the following two structs:
template<typename T>
struct one { /* ... */ };
template<template<typename...> typename T>
struct two { /* ... */ };
When I have example instantiated/uninstantiated templates like this:
template<typename T>
struct sample_templated { /* ... */ };
using instantiated = sample_templated<double>;
then I can do
one<instantiated>{};
two<sample_templated>{};
just fine. I would like to merge the definition of one
and two
such that they have the same name, though, as this would allow recursion.
I tried having a default definition like
template<typename...>
struct types_match_impl;
and having the two original structs be partial specializations of this, but this is incompatible with two
.
What is the solution here?
The way you're hoping for is not possible. Here's why:
one<instantiated>{};
two<sample_templated>{};
one
"uses" more than two
: It is referring to instantiated
which is sample_templated
instantiated with double
. two
on the other hand is only "using" the sample_templated
.
When you think of templates as functions on types, then this becomes even clearer: two
is a function which accepts a (type-level) function to create some type. one
is a function which accepts a type to create some type:
one :: T -> one<T>
two :: (T -> U) -> two<(T -> U)>
Put differently the parameter of one
has a different "kind" ("type of type") as the one of two
.
What you can do:
You can provide a specialization of one
which accepts a template template parameter ("type level function") and the template parameter for that:
template<template<typename...> typename TT, typename T>
struct one<TT<T>> { /* ... */ }; // this basically "calls" TT
You can turn two
into something which can accept both, albeit with a "dummy" template template parameter:
template<template<typename...> typename TT, typename... Ts>
struct two { /* */ };
template<typename...>
struct Void;
template<typename T>
struct two<Void<>, T> { /* Use T like in one */ };
// or derive from one<T>
There are probably more approaches, but these will depend on your specific use case.