Основные функции Typelist - PullRequest
       25

Основные функции Typelist

2 голосов
/ 09 октября 2011

У меня возникли некоторые проблемы с поиском списков типов или списков шаблонов. То есть:

class nulltype{};

template <typename HEAD, typename TAIL>
struct tlist
{
    typedef HEAD head;
    typedef TAIL tail;
}; 

template <class TList>
class OutputClass
{
public:
    void output(Type t) 
    {
        std::cout << t << endl;
    }
};

typedef tlist<double,tlist<float,NullType> > floatingPoints;    
typedef tlist<std::string,tlist<char *,NullType> > text;   

int main()
{
    OutputClass<floatingPoints> floats = OutputClass<floatingPoints>();
    floats.output(1.0f);

    OutputClass<text> strings = OutputClass<text>();
    floats.output("hello");
    return 0;
}

В основном моя цель состоит в том, чтобы я хотел, чтобы OutputClass.output выводил переданный ему параметр, но только если этот список типов экземпляров класса содержит тип, переданный в функцию. то есть. ссылаясь на приведенный выше код: float может выводить только тип float и тип double, как определено его списком типов, «FloatingPoints». Если строка или int будут переданы, я надеюсь, что это приведет к ошибке.

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

1 Ответ

3 голосов
/ 09 октября 2011

Сначала нам нужно несколько вспомогательных шаблонов.Первый проверяет, совпадают ли два типа:

template <typename T, typename U>
struct is_same
{
    // Default case: T and U are not the same type
    static const bool value = false;
};

template <typename T>
struct is_same<T, T>
{
    // Specialization: both template arguments are of the same type
    static const bool value = true;
};

Теперь мы можем использовать логическое значение is_same<T, U>::value, чтобы определить, эквивалентны ли типы T и U.

Используя is_same, мы можем теперь написать шаблон, который проверяет, встречается ли определенный тип в списке типов:

template <typename TList, typename T>
struct contains
{
    static const bool value =
         is_same<typename TList::head, T>::value   // Base case
      || contains<typename TList::tail, T>::value; // Recursion
};

template <typename T>
struct contains<nulltype, T>
{
    // Termination condition
    static const bool value = false;
};

Это рекурсивный шаблон, использующий специализацию на nulltype для завершения рекурсии.

Один последний вспомогательный шаблон, который нам нужен, это enable_if:

template <bool Cond, typename T=void>
struct enable_if
{
    // Default case: Cond assumed to be false, no typedef
};

template <typename T>
struct enable_if<true, T>
{
    // Specialization: Cond is true, so typedef
    typedef T type;
};

enable_if<true, T>::type и T, тогда как enable_if<false, T>::type не определено.Мы используем правило SFINAE , чтобы включить или отключить функцию в зависимости от аргумента шаблона, например:

template <typename TList>
class OutputClass
{
public:
    // Only enable the function if T is in TList (by SFINAE)
    template <typename T>
    typename enable_if<contains<TList, T>::value>::type
    output(T t) 
    {
        std::cout << t << std::endl;
    }
};

Довольно поездка, но если вы понимаете все это, вы хорошона вашем пути освоить шаблон метапрограммирования.Для более глубокого обсуждения шаблонного метапрограммирования я рекомендую вам взять копию C ++ Template Metaprogramming (ISBN-13: 9780321227256).

...