lundi 5 février 2018

g++ and clang++ different behaviour with pointer to variadic template functions

Another "who's right between g++ and clang++ ?" question for C++ standard gurus.

The code is the following

template <typename ...>
struct bar
 { };

template <typename ... Ts>
void foo (bar<Ts...> const &)
 { }

int main ()
 {
   foo<int>(bar<int, long>{});     // g++ and clang++ compile

   (*(&foo<int>))(bar<int, long>{});  // g++ and clang++ give error

   (&foo<int>)(bar<int, long>{});  // clang++ compiles; g++ gives error
 }

The template function foo() receive a variadic template parameter bar.

The first call

   foo<int>(bar<int, long>{});     // g++ and clang++ compile

works for both clang++ ang g++.

If I understand correctly, with foo<int> is explicated only the first template parameter and this doesn't complete the list of Ts... parameters. So the compiler look at the argument (a bar<int, long> object) and deduce the full list.

The second call is different

     (*(&foo<int>))(bar<int, long>{});  // g++ and clang++ give error

If I understand correctly, with (&foo<int>) we get the pointer to the instantiation of foo where Ts... is exactly int (not only the first type of the list but the whole list) and dereferencing it (*(&foo<int>)) and calling it with a wrong argument (a bar<int, long> object) we get (clang++ and g++) a compilation error.

So far, so good.

The problem arises with the third call

   (&foo<int>)(bar<int, long>{});  // clang++ compiles; g++ gives error

that I was convinced (maybe I was wrong) equivalent the second one (we fix all template types in Ts..., then we call the function with a wrong parameter) but g++ seems agree (and gives error) where clang++ disagree (and compile without problem).

The question, as usual, is: who's right ?

Aucun commentaire:

Enregistrer un commentaire