在 Concept 中使用带有 CRTP 的模板模板参数

Use a template template parameter with CRTP in a Concept

我想写一个 concept 来测试从基础 class 继承。

我的 Base class 被 Derived classes 公开继承,使用 CRTP。

这段代码工作正常:

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

...

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

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

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

编辑 - 第 8.3.5 节第 23 页template<typename T, typename U> concept bool C3 = true; 中的 Working Paper P0121R0 列表。因此,无论我在哪里读到 concept can take only one parameter 要么是过时的、错误的,要么是我读得不仔细。 结束编辑

我可以在这里访问我需要的其他类型 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(没有概念)