Использование SFINAE для определения модуля типа в C ++

StackOverflow https://stackoverflow.com/questions/534555

Вопрос

Оригинальное название здесь было Обходной путь для ошибки SFINAE в VS2005 C ++

Это предварительное использование SFINAE для создания эквивалента шаблонного класса is_pod, который существует в TR1 (в VS2005 TR1 еще нет).Он должен иметь свой значение член имеет значение true, когда параметр шаблона является типом POD (включая примитивные типы и созданные из них структуры) и false, когда это не так (например, с нетривиальными конструкторами).

template <typename T> class is_pod
{
  public:

    typedef char Yes;
    typedef struct {char a[2];} No;

    template <typename C> static Yes test(int)
    {
      union {T validPodType;} u;
    }
    template <typename C> static No test(...)
    {
    }
    enum {value = (sizeof(test<T>(0)) == sizeof(Yes))};
};

class NonPOD
{
  public:
    NonPod(const NonPod &);
    virtual ~NonPOD();
};

int main()
{
  bool a = is_pod<char>::value;
  bool b = is_pod<NonPOD>::value;
  if (a) 
    printf("char is POD\n");
  if (b)
    printf("NonPOD is POD ?!?!?\n");
  return 0;
}

Проблема в том, что в VS 2005 не только нет TR1, но и не будет заботиться о приведенном выше объединении (которое не должно быть допустимым, если параметр шаблона не является POD), поэтому оба a и b оцениваются как true .


Спасибо за ответы, опубликованные ниже.Внимательно прочитав их (и код) Я понял, что то, что я пытался сделать, на самом деле было неправильным подходом.Идея состояла в том, чтобы объединить поведение SFINAE с адаптацией к шаблону must_be_pod должен быть (который я нашел в книге Несовершенный C++, но его можно найти и в других местах).На самом деле, для этого потребовался бы довольно специфический набор правил для SFINAE, которые, очевидно, не соответствуют определению стандарта.В конце концов, на самом деле это не ошибка в VS.

Это было полезно?

Решение

Самая большая проблема с вашим подходом заключается в том, что вы не используете SFINAE здесь - SFINAE применяется только к типам параметров и возвращаемому типу здесь.

Однако из всех ситуаций SFINAE в стандарте ни одна не применима к вашей ситуации.Они такие

  • массивы с нулевыми значениями, ссылками, функциями или недопустимого размера
  • элемент типа, который не является типом
  • указатели на ссылки, ссылки на ссылки, ссылки на недействительные
  • указатель на элемент неклассового типа
  • недопустимые преобразования параметров значения шаблона
  • типы функций с аргументами типа void
  • тип функции const/volatile

Вероятно, именно поэтому в документации Boost есть:

Без некоторой (пока неуказанной) помощи от компилятора ispod никогда не будет сообщать, что класс или структура является POD;это всегда безопасно, если возможно неоптимально.В настоящее время (май 2005) только MWCW 9 и Visual C ++ 8 имеют необходимый компилятор-_intrinsics.

Другие советы

Это также не работает с VS2008, но я подозреваю, что вы это тоже знали.SFINAE предназначен для вывода аргументов шаблона для параметров шаблона;на самом деле вы не можете определить тип чего-либо, что раскрывает конструкторскую принадлежность типа, даже если вы можете создать тип, несовместимый с другим типом (т. Е. объединения не могут использовать non-POD).

Фактически, VS 2008 использует поддержку компилятором признаков для реализации std::tr1::type_traits.

Я не уверен в том, как вы пытаетесь сделать SFINAE здесь, поскольку is_pod<T>::test(...) будет соответствовать is_pod<T>::test(0) слишком.Возможно, если вы используете другой тип вместо 'int', вы получите лучшее соответствие:

template <typename T> class is_pod
{
  struct my_special_type { };
  public:
    typedef char Yes;
    typedef struct {char a[2];} No;

    template <typename C> static Yes test(my_special_type)
    {
      union {T validPodType;} u;
    }

    template <typename C> static No test(...)
    {
    }
    enum {value = (sizeof(test<T>(my_special_type())) == sizeof(Yes))};
};

Возможно, вы также захотите взглянуть на Повышение.Enable_i Включитьf, чтобы сделать ваш SFINAE за вас - если только вы не пытаетесь реализовать свою собственную библиотеку или по какой-либо причине.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top