адрес шаблонной функции c ++ - PullRequest
       82

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

20 голосов
/ 04 сентября 2010

Почему это не скомпилируется? (Г ++ - 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
}

Ответы [ 3 ]

13 голосов
/ 04 сентября 2010

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

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

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

0 голосов
/ 04 сентября 2010

Попробуйте

 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.С кодом, предоставленным в вопросе, можно было сделать следующее:

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

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

Как я и думал, OP хотелиспользуя ключевое слово c ++ 11 auto, как предложено тегом, я статически приводил h<int> к 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.

Пожалуйста, укажите причину отрицательных голосов.

0 голосов
/ 04 сентября 2010

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

Попробуйте

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

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