使用模板模板参数与概念中的CRTP

Use a template template parameter with CRTP in a Concept

本文关键字:CRTP 参数      更新时间:2023-10-16

我想写一个测试基类继承的concept

我的Base类使用CRTP被Derived类公开继承。

下面的代码运行正常:

#include <type_traits>
namespace NS
{
    template<typename D>
    class Base {
        // ...
    };
    class Derived : public Base<Derived>
    {
    public:
        constexpr Derived() = default;
        // ...
    };
}
template<typename D>
concept bool inheritsFromB() {
    return std::is_base_of<NS::Base<D>, D>::value;
}
template<inheritsFromB b>
void myFunct() {};
int main() {
    constexpr auto d = NS::Derived();
    using dType = typename std::decay<decltype(d)>::type;
    myFunct<dType>();
}

如果我想模板Derived,我遇到了一个问题。这可能吗?

namespace NS
{
    template<typename D, typename T>
    class Base { ... };
    template<typename T>
    class Derived : public Base<Derived<T>, T>
    { // ...
      // probably some using declaration for T? 
    };
}
template<template <typename> class D>
concept bool inheritsFromB() {
    return std::is_base_of<NS::B<D<T>,T>, D<T>::value;
}
...

明显的问题是,我没有T在我的concept声明。而且,我很确定我不能声明

template<template <typename> class D, typename T> 
concept bool inheritsFromB() {
... 
}

,因为concept需要一个模板参数。

编辑 -工作文件P0121R0列表在 8.3.5节,p23template<typename T, typename U> concept bool C3 = true;。因此,无论我在哪里读到concept只能取一个参数,要么是过时的,要么是错误的,要么是我读得不够仔细。结束编辑

我可以访问我在这里需要的其他类型T吗?是否有另一种方法(在我看来,模板类型D将携带它的类型T的信息,但我也不能使用using T = typename D<T>::valueType;,因为我需要T来指定D<T>的类型…)

我怀疑以下特征应该起作用:

#include <type_traits>
#include <utility>
namespace NS
{
    template <typename D, typename T>
    class Base {};    
    template <typename T>
    class Derived : public Base<Derived<T>, T> {};
}
namespace detail
{
    template <typename T, template <typename> typename D>
    std::true_type is_derived_from_base(const ::NS::Base<D<T>,T>*);
    std::false_type is_derived_from_base(void*);
}
template <typename T>
using is_derived_from_base = decltype(detail::is_derived_from_base(std::declval<T*>())); 
template <typename T>
concept bool inheritsFromB()
{
    return is_derived_from_base<T>{};
}

DEMO(不含概念)