2

I had the following line in some C++ code inside of a template function:

auto swapper = std::swap<T>;

And when compiling, using T=int, for instance, I get the following compiler error:

error: unable to deduce ‘auto’ from ‘swap<int>’
|  auto swapper = std::swap<T>;
|       ^~~~~~~
note:   couldn’t deduce template parameter ‘auto’

If I explicitly declare the type for swapper it works:

void (*swapper)(T&,T&) = std::swap<T>;

However, I am still puzzled as to why I can't declare swapper as auto?

markt1964
  • 2,638
  • 2
  • 22
  • 54
  • 1
    There are multiple overloads of `std::swap`. Unless you provide the type, the compiler can't know which of them you wish to take an address of. – Igor Tandetnik Jul 26 '20 at 03:01
  • @IgorTandetnik From what I can see there is only one possible overload once template arguments are known, and here they are explicitly provided. Interestingly, [clang compiles this just fine](https://coliru.stacked-crooked.com/a/9a0b51dbed39cbde) -- GCC does seem to choke, and I don't know why. – cdhowie Jul 26 '20 at 03:06
  • @eerorika Interesting. [GCC on coliru doesn't like it](https://coliru.stacked-crooked.com/a/71aa3de33f7bef59). Maybe a GCC bug fixed in a newer version? – cdhowie Jul 26 '20 at 03:09
  • @cdhowie I was using another language version: http://coliru.stacked-crooked.com/a/003a24f04a88d869 – eerorika Jul 26 '20 at 03:11
  • 1
    @cdhowie **[global.functions]/2** A call to a non-member function signature described in Clauses 21 through 33 and Annex D shall behave as if the implementation declared no additional non-member function signatures.(181) **Footnote 181**: ... An implementation may also define additional non-member functions that would otherwise not be called by a valid C++ program. – Igor Tandetnik Jul 26 '20 at 03:11
  • 3
    (May be) Unrelated: You shouldn't be doing this! Read more: [Can I take the address of a function defined in the standard library?](https://stackoverflow.com/questions/55687044/can-i-take-the-address-of-a-function-defined-in-standard-library) – JeJo Jul 26 '20 at 03:13
  • 2
    @JeJo Interesting, actually that seems quite related. This would fall under the umbrella of UB, it seems, so a compile-time error is probably the _best_ outcome here. I've been using C++ quite a long while and somehow never learned that taking the address of some standard library functions is UB. – cdhowie Jul 26 '20 at 03:15
  • While it doesn't change the UB, it should be noted that `std::swap` moved from `` to `` in C++11. Whether or not `` is included actually does affect whether I get an error, with both GCC and Clang. (e.g., [one with Clang failing](https://gcc.godbolt.org/z/heWqo8) and [one with GCC compiling it](https://gcc.godbolt.org/z/GfhG5q)) – chris Jul 26 '20 at 03:39
  • 1
    @cdhowie Taking the addess of a function template _is_ UB. – Michaël Roy Jul 27 '20 at 16:57
  • @MichaëlRoy I assume you mean an instantiation of a function template. I've not seen any evidence that doing so is UB in the general case. – cdhowie Jul 27 '20 at 17:11
  • @cdhowie No, I mean a template. An instantiation of a template, like std::swap, is already a function, as far as the compiler is concerned. – Michaël Roy Jul 27 '20 at 17:28
  • @MichaëlRoy Okay. So why are we talking about taking the address of a function template? It's not only UB, it's nonsense. I can't think of any compilers that will successfully compile such an operation. I can't even see where we've discussed such a thing in this thread. – cdhowie Jul 27 '20 at 19:44
  • I totally agree. Maybe because T is not a concrete type, I guess. But if blame should be given, look towards the original poster. But in the context of a site dedicated to help solve such issues, blame is a bit too harsh of a word, isn't it? – Michaël Roy Jul 28 '20 at 00:16
  • T is no less concrete in the above situation where I mentioned that it did work. I was asking specifically why `auto` doesn't work when that does. – markt1964 Jul 28 '20 at 15:36

0 Answers0