Suppose I have two classes:
template <typename X, typename Y>
class Functor {};
template <typename Start, typename End, typename ...Functors>
class Template {};
Template
has the constraints:
All
Functors
must be typeFunctor
All
Functor
must be in a chain sequence, such that- the first
Functor
must haveStart
as its first argument - the last
Functor
must haveEnd
as its second argument - each
Functor
's first argument is the second argument of theFunctor
preceding it
E.g.
Functor<A,B>, Functor<B, C>, Functor<C, D>, ...
etc.- the first
Example:
Starting with: char
Ending with: long
Template<char, long, Functor<char, A>, Functor<A, B>, Functor<B, C>, Functor<C, long>> t;
1 2 3 4
├─────────┼─────────┼─────────┼─────────┤
argument: char A B C long
Functor #
= 1 Functor<char, A>,
2 Functor<A, B>,
3 Functor<B, C>,
4 Functor<C, long>
Code
namespace ns
{
template <typename X, typename Y = X>
class Functor
{
public:
using first = X;
using second = Y;
Functor(X lVal) : x(lVal) {}
private:
X x;
};
template <typename Start, typename End, typename ...Functors>
requires(std::is_convertible_v<Functors, Functor> && ...) //error
class Template
{
// How does one use `std::is_convertible_v` on
// an un-specialized template class?
};
template <typename Start, typename End>
class Template<Start, End, Functor<Start, End>>
{};
}
Questions:
- What is the best approach?
- Can this be done with fold expression(s)?
- Or concepts?
- How does one use
std::is_convertible
(or any of the other metaprogramming traits) on an un-specialized template class?
std::same_as<void(Start, Y...), void(X..., End)>
... is one of the nicest things I've seen in a long time. Brilliant! – Zorazorah