Характеристики типа C ++ для извлечения класса параметров шаблона

В шаблоне я хочу развернуть параметр шаблона до реального не шаблонного типа. Так:

template <typename T>
struct MyTemplate
{
    // sadly there's no extract_Base
    typedef typename extract_base<T>::MyType WorkType;
};
struct X {};
template <typename T> struct Templ {};
//MyTemplate<Templ<X>>::WorkType is X;
//MyTemplate<X>::WorkType is X;

Единственное решение, которое я вижу, - это определить реальный базовый тип, такой как std :: vector ‹X› :: value_type is X. Но мне любопытно, есть ли способ сделать это без определения вспомогательных типов внутри каждого шаблона назначения.

Я видел что-то вроде http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2965.html но это черновик? и я не совсем понимаю.

Да, я знаю, что существует множественное наследование, но даже для простого случая это было бы неплохо.

ОБНОВЛЕНИЕ: решение Nawaz работает для меня очень хорошо, и его легко распространить на конкретные случаи, например

template<template<typename, typename> class X, typename T1, typename T2>
struct extract_base <X<T1, T2>>   //specialization
{
    typedef T1 base;
};

Я даже могу применить is_base_of или другие фильтры к T1 / T2 и так далее. Так что это действительно работает для X ‹T, U› - по крайней мере, с g ++ 4.6.7.


person queen3    schedule 15.06.2012    source источник
comment
Это не имеет ничего общего с наследованием или базовыми классами.   -  person Ben Voigt    schedule 15.06.2012
comment
Есть std::is_base_of, но это может не полностью соответствовать вашим целям.   -  person dirkgently    schedule 15.06.2012


Ответы (1)


Прежде всего, давайте назовем его value_type вместо base, потому что value_type кажется более подходящим термином для описания типа, который вы хотите извлечь.

Вы можете использовать это:

template<typename T>
struct extract_value_type //lets call it extract_value_type
{
    typedef T value_type;
};

template<template<typename> class X, typename T>
struct extract_value_type<X<T>>   //specialization
{
    typedef T value_type;
};

Он должен работать, пока аргумент шаблона для extract_value_type имеет форму T или X<T>. Однако для X<T,U> это не сработает. Но тогда это легко реализовать на C ++ 11 с использованием вариативного шаблона.

Используйте это как:

template <typename T>
struct MyTemplate
{
    typedef typename extract_value_type<T>::value_type value_type;
};

Онлайн-демонстрация: http://ideone.com/mbyvj


Теперь в C ++ 11 вы можете использовать вариативный шаблон, чтобы extract_value_type работать с шаблонами классов, которые принимают более одного аргумента шаблона, например std::vector, std::set, std::list и т. Д.

template<template<typename, typename ...> class X, typename T, typename ...Args>
struct extract_value_type<X<T, Args...>>   //specialization
{
    typedef T value_type;
};

Демонстрация: http://ideone.com/SDEgq

person Nawaz    schedule 15.06.2012
comment
Компилируется с шаблоном ‹typename› class X и работает! Спасибо. - person queen3; 15.06.2012
comment
@ queen3: Теперь посмотрим на вариативное решение. - person Nawaz; 15.06.2012
comment
Да хоть X ‹T, U› у меня работали, см. Update. Тем не менее это было то, что мне было нужно. - person queen3; 15.06.2012
comment
@ queen3: я переименовал имя структуры и вложенный тип. Смотрите сейчас. value_type подходит больше, чем base. - person Nawaz; 15.06.2012
comment
Что ж, в моем случае это шаблон X ‹T›: public T, так что это действительно основа. - person queen3; 15.06.2012
comment
@ queen3: Ох .. Понятно. В этом случае std::is_base_of также может помочь. - person Nawaz; 15.06.2012
comment
И мне нужен typedef typename extract_base ‹T1› :: base base; для рекурсивного путешествия на глубокую базу ... о боже. - person queen3; 15.06.2012
comment
is_base_of не поможет, так как я вообще не знаю конкретных типов. Мне просто нужен какой-нибудь первый не шаблонный тип. - person queen3; 15.06.2012
comment
@ queen3: Хорошо. Надеюсь, мой ответ поможет вам решить вашу настоящую проблему. - person Nawaz; 15.06.2012