Подтвердить что ты не робот

Адрес функции шаблона С++

Почему это не удается скомпилировать? (g++ - 4.5)

template < typename U >
static void h () {
}

int main () {
  auto p = &h<int>; // error: p has incomplete type
}

РЕДАКТИРОВАТЬ: Вот работа:

template < typename U >
static void h () {
}

int main () {
  typedef decltype (&h<int>) D;
  D p = &h<int>; // works
}
4b9b3361

Ответ 1

В С++ 0x это гарантировано. Однако в С++ 03 это не работало (часть инициализатора, то есть), а некоторые компиляторы, по-видимому, еще не поддерживают его.

Кроме того, я помню, что формулировка С++ 0x не ясна, что происходит с &h<int>, когда она является аргументом шаблона функции и выведен соответствующий параметр (это то, что auto переводится, концептуально). Однако намерение состоит в том, что оно действительно. См. этот отчет о дефектах, где они разработали формулировку, пример "Нико Йосуттис" и их последний пример.

Существует другое правило, которое формулирует, но компиляторы неправильно реализуют. Например, см. Этот clang PR.

Ответ 2

Он не компилируется, потому что тип 'p' не известен компилятору, который является обязательным в С++, в отличие от некоторых других языков.

Try

template < typename U > 
static void h () { 
} 

int main () { 
  auto void (*p)() = &h<int>; 
} 

Ответ 3

Try

 auto p  = static_cast<void(*)()>(& h<int>);

Потому что gcc рассматривает шаблонную функцию как перегруженную. С точки зрения gcc это похоже на то, что у вас есть h(int param) и h(float param) - какой компилятор должен выбрать?

Я заметил, что было проблемой в более старых версиях gcc, но я попытаюсь объяснить это более подробно. GCC не смог вывести тип, потому что шаблонная функция обрабатывалась как перегруженная. Это было похоже на то, что у вас будет следующее:

void h(int)
{
}

void h(float)
{
}

void (*p)(int) = & h;  //ok
void (*p)(float) = & h; //ok
auto p = & h; //error: which version of h?

Для gcc h<int> была похожа на перегруженную функцию h с бесконечными альтернативами в зависимости от параметра T. С кодом, о котором идет речь, был O.K. для выполнения следующих действий:

void (*p)() = & h<int>;

(вот почему я не набираю "обход" )

Поскольку я думал, что OP хочет использовать ключевое слово С++ 11 auto, как было предложено тегом, я статически выбрал h<int> to void(*)(), который вроде бы не работает, просто для трюка gcc, потому что он не имел возможности правильно обрабатывать шаблонные функции и auto.

Функции void h<int>() и void h<float>() должны, конечно, рассматриваться как разные функции с одним и тем же типом указателя, а не с перегрузкой версий функции h. При создании экземпляра они должны вести себя как void hInt() и void hFloat(), и вы должны иметь возможность использовать auto, как здесь:

void hInt()
{
}

void hFloat()
{
}

auto p = hInt;
p = hFloat;

Но почему-то для gcc они были похожи на перегруженные версии h.

Просьба указать причину падения.