23

The following snippet compiles fine in vc++ and clang++, but fails on gcc (inc 9.2) unless i add an explicit cast. Which compiler is right here?

#include <initializer_list>

template<typename T>
void Task(void) {}

int main()
{
    for(auto p_task: {&Task<int>}) {} // error
//  for(auto p_task: {static_cast<void (*)(void)>(&Task<int>)}) {} // ok
}
<source>: In function 'int main()':
<source>:8:33: error: unable to deduce 'std::initializer_list<auto>&&' from '{(& Task<int>)}'
    8 |     for(auto p_task: {&Task<int>}) {} // error
      |                                 ^
<source>:8:33: note:   couldn't deduce template parameter 'auto'

online compiler

user7860670
  • 35,849
  • 4
  • 58
  • 84
  • 8
    Note: You don't need a range-based loop to cause this problem. `auto l = { &Task };` does the same ([live demo](https://godbolt.org/z/EtAhGS)). – Daniel Langr Dec 29 '19 at 10:11
  • 5
    This seems like a bug in the gcc compiler. Interestingly, it works if you do `+Task` which implies the `&Task` might have a type ambiguity in gcc that's not present for implicit conversion. For instance gcc might simply ignore the `&` when applied to a global function, which then has an ambiguity of `void(*)()` vs `void()` or `void(&)()`. Or something... I'd send in a ticket. – Cruz Jean Dec 29 '19 at 16:46
  • 10
    Filed [gcc 93107](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93107). – Barry Dec 30 '19 at 14:52
  • 3
    To add more information, this will compile on gcc: `{ std::addressof(Task) }` which may help you with a possibly more pleasing workaround (though the unary plus is always a crowd pleaser). – Jody Hagins Feb 03 '20 at 04:02
  • @Barry Fix committed to GCC master on 2020-10-29 20:12:19 UTC; gcc trunk now successfully compiles the live demo. – Bulletmagnet Nov 12 '20 at 12:13

1 Answers1

1

GCC was wrong, but not anymore! Thanks to @Barry reporting it, and Marek Polacek fixing it, the live demo can now be compiled with GCC trunk (future GCC 11).

Bulletmagnet
  • 5,665
  • 2
  • 26
  • 56