2015-10-21 2 views
3

Я хочу написать concept, который проверяет наследование из базового класса.Используйте параметр шаблона шаблона с CRTP в концепции

Класс 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; 
} 

... 

очевидная проблема в том, что у меня в моей concept декларации нет T. Кроме того, я уверен, что я не могу объявить

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

поскольку concept требует один параметр шаблона.

Edit - в Working Paper P0121R0 списки в разделе 8.3.5, P23, template<typename T, typename U> concept bool C3 = true;. Следовательно, везде, где я читал concept, может принимать только один параметр, либо был устаревшим, либо неправильным, либо я читал, что ему не хватает заботы. end Редактировать

Могу ли я получить доступ к другим типам T, которые мне нужны здесь? Есть ли альтернативный способ (мне кажется, что тип шаблона D будет нести информацию о том, что это тип T, но я также не могу использовать using T = typename D<T>::valueType;, потому что мне нужен T для определенного типа D<T> ...)

ответ

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 (без понятий)

+0

Выглядит хорошо - я вложенными в 'detail' имен внутри' NS', а затем переехал 'используя is_derived_from_base' декларацию в 'NS' также, так что мой con Теперь cept использует 'NS :: is_derived_from_base'. Спасибо за ответ! – chrisb2244

Смежные вопросы