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

时间:2015-10-21 05:35:02

标签: c++ templates c++17 c++-concepts

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

我的Base类由Derived类公开继承,使用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;
}

...

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

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,只能使用一个参数,或者过时,错误,或者我读得不够谨慎。 结束编辑

我可以访问我需要的其他类型T吗?是否有另一种方式(在我看来,模板类型D会包含T类型的信息,但我也不能使用using T = typename D<T>::valueType;,因为我需要T以特定类型D<T> ...)

1 个答案:

答案 0 :(得分:2)

我怀疑以下特征应该有效:

#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(没有概念)