2015-09-09 3 views
0

Я пытаюсь утверждать, что параметр шаблона будет получен из некоторого базового класса. Но базовый класс является общим и в контексте утверждения нет никакой разницы между любыми типами специализации. Как я могу утверждать, что параметр шаблона был получен из общего типа любого специализированного типа?is_base_of общего типа

Я пытаюсь написать это как

base_generic:

template<typename T> struct base_generic{}; 

derived_generic:

template<typename T> struct derived_generic : public base_generic<T>{}; 

класс с утверждением:

template<typename Tsource, typename Tderived_generic> 
struct encoder { 
static_assert(std::is_base_of<base_generic<typename>, Tderived_generic>::value); 
}; 

Этот код компилируется, но утверждение f ails

+0

Вы имеете в виду что-то вроде 'template struct base_generic {}; struct found_generic: base_generic {}; '? – TartanLlama

+2

Пожалуйста, напишите объявления для 'base_generic' и' deriv_generic'. – TartanLlama

+0

Дайте минимальный, но полный образец того, что вы на самом деле делаете, пожалуйста. –

ответ

1

Из комментария @PiotrSkotnicki

template <template <typename...> class Base, typename Derived> 
struct is_base_of_template 
{ 
    using U = typename std::remove_cv<Derived>::type; 

    template <typename... Args> 
    static std::true_type test(Base<Args...>*); 

    static std::false_type test(void*); 

    using type = decltype(test(std::declval<U*>())); 
}; 

template <template <typename...> class Base, typename Derived> 
using is_base_of_template_t = typename is_base_of_template<Base, Derived>::type; 

Это решение работает хорошо, example.

-1

вы можете использовать static_assert.

См: http://en.cppreference.com/w/cpp/language/static_assert

Так, например, если у вас есть базовый класс

template< typename T > 
class Base<T> {}; 

и производный один

template< typename T > 
class Derived : public Base<T> {}; 

с вашим использованием случай

template< typename Tsource, typename Tstorage > 
class Test 
{ 
    std::static_assert(std::is_base_of< base<T>, TStorage >::value); 
} 

Невозможно получить T без добавления его в качестве параметра шаблона.

Но с помощью простого трюка вы его получите. Вы должны добавить typedef к производному:

И вы можете использовать его внутри статического утверждения.

template< typename Tsource, typename Tstorage > 
class Test 
{ 
    std::static_assert(std::is_base_of< base<TStorage::value_type>, TStorage >::value); 
} 

Поскольку Tstorage является производным, он имеет поле value_type.

+0

почему downvote? – Gombat

+1

Ответы только на связь не приветствуются. Кроме того, это не отвечает на его вопрос. – TartanLlama

+0

ОП спрашивает, как использовать эту вещь для утверждения другой вещи. – edmz

2

Вы можете создать признак для того, что-то вроде:

namespace detail 
{ 
    template <template <typename > class C> 
    struct is_base_of_any_helper 
    { 
     template <typename T> 
     std::true_type operator()(const C<T>*) const; 

     std::false_type operator() (...) const; 

    }; 

} 

template <template <typename > class C , typename T> 
using is_base_of_any = 
    decltype(detail::is_base_of_any_helper<C>{}(std::declval<const T*>())); 

Demo

Обратите внимание, что она потерпит неудачу с некоторыми крайними случаями, такими как:

  • нескольких баз C<Tx>
  • частное наследство C<T>.