2017-02-07 5 views
0

Я пытаюсь обернуть мою голову вокруг специализации шаблона, и я немного запутался (возможно, не понимая, что имяТип на самом деле, или то, что ожидает, что компилятор)Не понимание C++ шаблон специализации и Константа

Пример 1 (Собирает):

template <typename A, typename... Args> 
class Example 
{ 
public: 
    Example(){} 
    virtual ~Example(){} 
}; 

template <typename A, typename... Args> 
class Example<A, int, Args...>{ 
    Example(){} 
    virtual ~Example(){} 
}; 

Пример 2 (компилирует):

template <typename A, int, typename... Args> 
class Example 
{ 
public: 
    Example(){} 
    virtual ~Example(){} 
}; 

template <typename A, typename... Args> 
class Example<A, 2, Args...>{ 
    Example(){} 
    virtual ~Example(){} 
}; 

Пример 3 (Сбой):

template <typename A, typename... Args> 
class Example 
{ 
public: 
    Example(){} 
    virtual ~Example(){} 
}; 

template <typename A, typename... Args> 
class Example<A, 2, Args...>{ 
    Example(){} 
    virtual ~Example(){} 
}; 

Ошибка является:

ошибки: тип/рассогласование значения в аргументе 2 в списке параметров шаблона для «класса шаблона Примера

Вопросы:

Во-первых, я новичок в родовом программировании, и я надеюсь, что задаю вопрос t вопросов. Терминология спецификации компилятора по-прежнему немного чуждо мне.

  • Что происходит? Компилятор пытается обрабатывать константу как typename?
  • Если typename может быть специализированным как int, а int может быть специализированным как 2, почему не может быть названо typename как 2?
  • Что было бы «правильным» методом для специализации класса с int или enum?
  • Я задаю правильные вопросы?

Спасибо

EDIT/Решение:

После того как я понял, что происходит (из объяснения Yakk в), вот как мое окончательное решение выглядит. Я где-то читал один из гуру C++: «Вы можете решить любую проблему, добавив еще один слой абстракции». Теперь я знаю, что это значит: D

enum ETypes 
{ 
    UNKNOWN = 0, 
    INT = 1, 
    FLOAT = 2, 
    STRING = 3, 
    FUNC = 4, 
}; 

// This is to use the ETypes as a type. 
// Note that T is not a type, hence use it as RHS 
template<ETypes T> 
class ETypeName 
{ 
public: 
    ETypes type = T; 
}; 


// The example 
template <typename A, typename... Args> 
class Example 
{ 
private: 
    Example();    // Hide the constructor as private 
          // to generate compilation error 
    virtual ~Example(){} 
}; 


// LOOK! We can use the Enum to specialize the class. 
template <> 
class Example<ETypeName<ETypes::INT>>{ 
public: 
    ETypes mType; 
    Example():mType(ETypes::INT){} 
    virtual ~Example(){} 
}; 

И в основной():

Example<ETypeName<ETypes::INT>> x; 

    // This can't happen. Private constructor. Not specialized yet 
// Example<ETypeName<ETypes::FLOAT>> x1; 
+1

Параметры шаблона непигового типа отличаются от параметров шаблона шаблона. В сущности, да, 2 рассматривается как непиковый параметр, но класс шаблона ожидает тип. – user975989

+0

А, так что это то, чего мне не хватало – Makketronix

ответ

2

Основная специализация выглядит следующим образом:

template <typename A, typename... Args> 
class Example 

При вводе Example<stuff goes here>, это всегда сопоставляется список <typename A, typename... Args> аргументов в первичной специализации в.

Это совершенно другое животное:

template <typename A, typename... Args> 
class Example<A, int, Args...> 

Это вторичная специализация. Здесь

template <typename A, typename... Args> 

является не списка аргументов, а список вычета.

Список аргументов:

class Example<A, int, Args...> 

здесь. То, что находится между <>, используется только для сопоставления шаблону против аргументов, переданных первичной специализации.

Типы и параметры нестандартного шаблона - это разные вещи. Основная специализация описывает, какие аргументы являются типом, и какие аргументы не являются типом.

Как только они сопоставлены с первичным, каждая из вторичных специализаций имеет шаблон, сопоставляемый с аргументами. Рассматривается каждый жизнеспособный кандидат, и для определения «более специализированного» используется разумно сложная система, правила которой я не буду здесь останавливаться.

+0

Я принимаю это как ответ для уточнения определений и терминологии и объяснения того, как они работают на более глубоком уровне, на котором я не подвергался. – Makketronix

2

What is happening? Is the compiler trying to treat the constant as typename?

Да.

If typename can be specialized as int, and int can be specialized as 2, why can't a typename be specialized as 2?

параметра шаблона, начиная с typename требует типа в качестве аргумента. В вашем втором примере вторым параметром шаблона является int, а не typename something. Таким образом, он не ожидает тип как аргумент, а фактическое значение int.

В третьем примере используется определение шаблона, которое ожидает только параметры шаблона typename, но вы попытаетесь присвоить значение int в качестве аргумента. Вот почему вы получаете ошибку.

What would be a "proper" method to specialize the class with int or enum?

Не уверен, что правильно понял смысл вопроса. Правильный способ специализации вашего шаблона для экземпляров с использованием второго параметра шаблона int - это ваше второе определение шаблона.