Как определить, является ли тип производным от шаблонного класса? - PullRequest
11 голосов
/ 14 мая 2011

Как я могу определить, является ли тип производным от шаблонного класса?В частности, мне нужно определить, имеет ли параметр шаблона std::basic_ostream в качестве базового класса.Обычно std::is_base_of является инструментом для работы.Однако std::is_base_of работает только для полных типов, а не шаблонов классов.

Я ищу что-то подобное.

template< typename T >
bool is_based_in_basic_ostream( T&& t )
{
   if( std::is_base_of< std::basic_ostream< /*anything*/>, T >::value )
   {
      return true;
   }
   else
   {
      return false;
   }
}

Я уверен, что это можно сделать, я не могуподумай как.

Ответы [ 2 ]

13 голосов
/ 14 мая 2011

Я не знаю краткого и краткого пути.Но вы можете снова злоупотреблять перегрузкой

template< typename T, typename U >
std::true_type is_based_impl( std::basic_ostream<T, U> const volatile& );
std::false_type is_based_impl( ... );

template< typename T >
bool is_based_in_basic_ostream( T&& t ) {
  return decltype(is_based_impl(t))::value;
}

Это только обнаружит публичное наследование.Обратите внимание, что вместо этого вы можете обнаружить деривацию из ios_base, которая может работать для вас одинаково хорошо (этот тест также будет положительным для входных потоков, поэтому он имеет ограниченную применимость)

std::is_base_of<std::ios_base, T>
5 голосов
/ 14 мая 2011

Может быть что-то вроде Boost's is_instance_of будет тем, что вы ищете?

http://www.boost.org/doc/libs/1_46_1/boost/lambda/detail/is_instance_of.hpp

Вот краткая версия для шаблонов с одним аргументом:

#include <iostream>
#include <type_traits>

template <template <typename> class F>
struct conversion_tester
{
        template <typename T>
        conversion_tester (const F<T> &);
};

template <class From, template <typename> class To>
struct is_instance_of
{
        static const bool value = std::is_convertible<From,conversion_tester<To>>::value;
};

template <typename T>
struct foo {};

template <typename T>
struct bar {};

int main()
{
        std::cout << is_instance_of<foo<int>,foo>::value << '\n'; // This will print '1'.
        std::cout << is_instance_of<bar<int>,foo>::value << '\n'; // This will print '0'.
}

К сожалению, если вы попытаетесь расширить это до шаблонов с переменными параметрами, с текущим GCC (4.6.0) он выдаст сообщение об ошибке. Этот ответ SO подразумевает, что в настоящее время это проблема GCC и что версия шаблона с вариадическим кодом должна работать в соответствии со стандартом.

...