Почему тип указателя Cast не работает с шаблоном Параметры непикового типа
У меня есть следующий код:
template <const char *p>
struct A{};
template <int i>
struct E{};
extern constexpr int i = 0;
constexpr float f = 0.f;
extern constexpr char c = 0;
int main(int argc, const char *argv[])
{
A<&c> b; //works
A<(const char *)(&i)> a; //Error: could not convert template argument ‘(const char*)(& i)’ to ‘const char*’
E<(int)f> e; //works
return 0;
}
почему строка A<(const char *)(&i)> a;
неверна? Я скомпилировал его с g++ - 4.6.1 с -std = С++ 0x.
EDIT: поскольку Чарльз предположил, что reinterpret_cast
не допускается в постоянном выражении, я изменяю приведенный выше код на следующее:
struct Base{};
struct Derived : public Base {};
template <const Base *p>
struct A{};
extern constexpr Base base = {};
extern constexpr Derived derived = {};
A<&base> a; //works
A<(const Base*)&derived> b; //error: could not convert template argument ‘(const Base*)(& derived)’ to ‘const Base*’
Следовательно, не только reinterpret_cast
не допускается. Использование A<static_cast<const base*>(&derived)
дает ту же ошибку.
To @BЈовић:
A<(const Base*)(0)> b; // error: could not convert template argument ‘0u’ to ‘const Base*’
Ответы
Ответ 1
Что касается ответов "стандарт говорит так", посмотрите комментарии.
Реальный вопрос: почему это не допустимо?
Это имеет смысл категорически отказаться от преобразования типов в аргументах шаблона, потому что то, что вас действительно интересует, - это значение аргумента шаблона. Преобразования типов, однако, могут стать произвольно сложными и не должны быть constexpr
s. Стандартный (по-видимому) просто не делает исключение для встроенных (примитивных) типов.
Обратите внимание, что ваш пример E<(int)f>
также опровергается clang
по причине:
error: аргумент типа non-type типа 'int' не является интегральным постоянным выражением
Почему gcc позволяет это сомнительно, но я бы предположил, что он позволяет использовать constexpr
, который вы можете явно объявить. Обратите внимание, что это невозможно, чтобы прокрасть адрес i
в списке параметров A
.