0 не является допустимым FILE *, если предоставляется в качестве аргумента шаблона - PullRequest
2 голосов
/ 31 марта 2010

следующий код

#include <stdio.h>
template <typename T, T v> class Tem
{
    T t;
    Tem()
    {
        t = v;
    }
};

typedef Tem<FILE*,NULL> TemFile;

при компиляции в файл .mm (Objective C ++) с помощью Xcode на MacOS X выдает следующую ошибку:

ошибка: не удалось преобразовать аргумент шаблона '0' в 'FILE *'.

Что происходит, пожалуйста? Рассматриваемый код прекрасно скомпилирован под MSVC. С каких пор константа 0 не является допустимым указателем на что-либо? Является ли это артефактом Objective C ++ (в отличие от vanilla C ++)?

Ответы [ 2 ]

1 голос
/ 31 марта 2010

Согласно стандарту, вам не повезло. Невозможно инициализировать аргумент указателя на что-либо, кроме адреса глобальной переменной. §14.3.2 / 1:

Шаблон-аргумент для не-типа, шаблонный параметр-шаблон должен быть одним из:

  • целочисленная константа-выражение целого или перечислимого типа; или
  • имя нетипового шаблона-параметра; или
  • адрес объекта или функции с внешней связью, в том числе шаблоны функций и функции идентификаторы шаблона, но исключая нестатические ученики, выраженные как & id-выражение, где & является необязательным если имя относится к функции или массив, или если соответствующий параметр-шаблона является ссылкой; или
  • указатель на член, выраженный как описано в 5.3.1.

§14.3.2 / 5:

  • для нетипового шаблона-параметра указатель типа на объект, квалификация преобразования (4.4) и преобразование массива в указатель (4.2) применяется. [Примечание: в частности, ни преобразование нулевого указателя (4.10) ни преобразование производного в основание (4.10) применяются. Хотя 0 является действительным шаблон-аргумент для нетипичного шаблон-параметр целочисленного типа, это не правильный шаблон-аргумент для нетипового шаблона-параметра тип указателя ]

Однако Comeau принимает этот недействительный обходной путь:

typedef Tem<FILE*, (FILE *) NULL > TemFile;

И у этого кода есть небольшая вероятность соответствия: я не могу найти, где стандарт конкретно говорит, что выражение по умолчанию используется дословно вместо отсутствующего аргумента, и я не могу найти соответствующий известный дефект. У кого-нибудь есть ссылка?

#include <stdio.h>
template <typename T, T *v = (T*) 0> class Tem
{
    T t;
    Tem()
    {
        t = v;
    }
};

typedef Tem<FILE> TemFile;

Для большей переносимости, вы можете рассмотреть возможность создания фиктивного FILE FILE_NULL;, передачи &FILE_NULL и проверки на равенство указателей с этим вместо нуля.

0 голосов
/ 31 марта 2010

Вы пробовали что-то подобное?

typedef Tem<FILE*,((FILE*)NULL)> TemFile;

Возможно, он пытается выяснить тип NULL.

...