#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, она не работает с заголовками.