Типовые признаки — явная специализация шаблона. сбой в xcode

#c #templates #icc

#c #шаблоны #icc

Вопрос:

Я пытаюсь использовать черты типа, как в «Современном дизайне C «, используя шаблон, чтобы определить, имеет ли тип переменный размер или нет. например, для строки требуется хранилище переменного размера, для int-хранилища фиксированного размера. Этот код работает на Microsoft C , теперь я переношу на Mac и получаю ошибку:

явная специализация не разрешена в текущей области

Как правильно специализировать это?

 template <typename T>
class MyTypeTraits
{
    template<class U> struct VariableLengthStorageTraits
    {
        enum { result = false };
    };
    template<> struct VariableLengthStorageTraits<std::wstring>
    {
        enum { result = true };
    };

public:
    enum{ IsVariableLengthType = VariableLengthStorageTraits<T>::result };
};
  

Комментарии:

1. Строка также имеет «хранилище фиксированного размера», в зависимости от того, что вы подразумеваете под «хранилищем».

2. В этом случае я сериализую объекты на диск. С целыми числами я просто сохраняю 4 байта. С помощью строк или массивов я сначала сохраняю количество элементов, а затем фактические элементы. Итак, этот код помогает мне хранить необработанные байты объектов в наиболее компактном формате.

3. также проблема в недавнем icc с std = c 14

Ответ №1:

Стандарт C 2003 допускает специализацию шаблона-члена только за пределами определения заключающего класса. Кроме того, специализация вне определения должна быть явной полной специализацией вложенного шаблона. Microsoft C нестандартен в этом отношении. Исправление простое, просто переместите внутренний шаблон из вложенного шаблона, поскольку внутреннему шаблону не нужны его аргументы шаблона вложенного класса:

 template<class U> struct VariableLengthStorageTraits
{
    enum { result = false };
};

template<>
struct VariableLengthStorageTraits<std::wstring>
{
    enum { result = true };
};

template <typename T>
struct MyTypeTraits
{
    enum{ IsVariableLengthType = VariableLengthStorageTraits<T>::result };
};
  

Ответ №2:

Вы не можете добавлять специализации вложенных классов внутри определения внешнего класса. Было бы проще и более многократно используемым сделать класс внутренних признаков отдельной сущностью, хотя:

 #include <type_traits>

template <typename> struct has_variable_length;  // intentionally undefined!
template <> struct has_variable_length<std::wstring> : std::true_type  { };
template <> struct has_variable_length<int>          : std::false_type { };
// ...

template <typename T> struct MyTraits
{
  static const bool variable_length = has_variable_length<T>::value;
  // ...
};
  

Вы могли бы обернуть отдельные классы признаков в detail пространство имен, если хотите.

Ответ №3:

Переместите специализацию функции за пределы класса и внутрь файла .cpp, она не работает с заголовками.