c++20 - 如何将模板参数包参数限制为“链”序列,例如F<A,B>、F<B,C>、F<C, D>?

问题描述 投票:0回答:1

假设我有两节课:

template <typename X, typename Y> class Functor {};

template <typename Start, typename End, typename ... Functors> class Template {};

Template
有限制:

  • 所有

    Functors
    必须为
    Functor

    类型
  • 所有

    Functor
    必须处于序列中,使得

    • first
      Functor
      必须将
      Start
      作为其 first 参数
    • last
      Functor
      必须将
      End
      作为其 second 参数
    • 每个
      Functor
      first 参数是其前面的 Functor
      second
      参数

    例如

    Functor<A,B>, Functor<B, C>, Functor<C, D>, ...
    等等

示例:

开始于:

char

结尾为:

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>

代码

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>>
    {};
}

问题:

  1. 最好的方法?
    • 这可以用折叠表达式来完成吗?
    • 或者概念?
  2. 如何在非专用模板类上使用
    std::is_convertible
    (或任何其他元编程特征)?

如果您已经完成了这一步,感谢您抽出宝贵的时间,并提前感谢您提供的任何信息。

c++ templates c++20 template-meta-programming c++-concepts
1个回答
0
投票

以下似乎有效。这给出了

Functor
正确序列的基本检查,并将其转化为概念,或添加类型特征样式
using
包装器等......,可以作为家庭作业:

class Start;
class End;

template <typename X, typename Y> class Functor {};

template<typename required, typename NextFunctor,
     typename ...RemainingFunctors> struct FunctorValidate;

template<typename required>
struct FunctorValidate<required, Functor<required, End>> {

    typedef void type_t;
};

template<typename required, typename NextFunctorType,
    typename FirstRemainingFunctor, typename ...RemainingFunctors>
struct FunctorValidate<required, Functor<required, NextFunctorType>,
    FirstRemainingFunctor, RemainingFunctors...>
    : FunctorValidate<NextFunctorType, FirstRemainingFunctor,
              RemainingFunctors...>
{
};

template<typename ...AllFunctors> struct FunctorChain
    : FunctorValidate<Start, AllFunctors...>
{
};

class A;
class B;
class C;

typedef FunctorChain<Functor<Start, A>,
             Functor<A, B>,
             Functor<B, C>,
             Functor<C, End>>::type_t ok1;

typedef FunctorChain<Functor<Start, End>>::type_t ok2;

#if 0
typedef FunctorChain<Functor<A, B>,
             Functor<B, C>,
             Functor<C, End>>::type_t error1;

typedef FunctorChain<Functor<Start, A>,
             Functor<A, B>,
             Functor<B, C>>::type_t error2;

typedef FunctorChain<Functor<Start, A>,
             Functor<B, C>,
             Functor<C, End>>::type_t error3;

#endif
© www.soinside.com 2019 - 2024. All rights reserved.