4

I am observing some strange behavior that I can't quite explain myself. The code looks like this:

#include <memory>
#include <vector>
#include <algorithm>

int main(){
    std::vector<double> t1(10, 5.0);
    std::vector<double*> t2(10);
    std::transform(t1.begin(), t1.end(), t2.begin(), std::addressof<double>);
    //std::transform(t1.begin(), t1.end(), t2.begin(), [](double& a){return &a;});
}

And here is a version to play around with https://godbolt.org/g/YcNdbf The problem is that this code compiles fine using gcc4.9-6.3 but fails under gcc 7.1. Clang doesn't like it either.

(edit) Error messages from gcc 7.1:

<source>: In function 'int main()':
8 : <source>:8:76: error: no matching function for call to 'transform(std::vector<double>::iterator, std::vector<double>::iterator, std::vector<double*>::iterator, <unresolved overloaded function type>)'
     std::transform(t1.begin(), t1.end(), t2.begin(), std::addressof<double>);
                                                                            ^
In file included from /opt/compiler-explorer/gcc-7.1.0/include/c++/7.1.0/algorithm:62:0,
                 from <source>:3:
/opt/compiler-explorer/gcc-7.1.0/include/c++/7.1.0/bits/stl_algo.h:4281:5: note: candidate: template<class _IIter, class _OIter, class _UnaryOperation> _OIter std::transform(_IIter, _IIter, _OIter, _UnaryOperation)
     transform(_InputIterator __first, _InputIterator __last,
     ^~~~~~~~~
/opt/compiler-explorer/gcc-7.1.0/include/c++/7.1.0/bits/stl_algo.h:4281:5: note:   template argument deduction/substitution failed:
8 : <source>:8:76: note:   could not resolve address from overloaded function 'addressof<double>'
     std::transform(t1.begin(), t1.end(), t2.begin(), std::addressof<double>);
                                                                            ^
In file included from /opt/compiler-explorer/gcc-7.1.0/include/c++/7.1.0/algorithm:62:0,
                 from <source>:3:
/opt/compiler-explorer/gcc-7.1.0/include/c++/7.1.0/bits/stl_algo.h:4318:5: note: candidate: template<class _IIter1, class _IIter2, class _OIter, class _BinaryOperation> _OIter std::transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation)
     transform(_InputIterator1 __first1, _InputIterator1 __last1,
     ^~~~~~~~~
/opt/compiler-explorer/gcc-7.1.0/include/c++/7.1.0/bits/stl_algo.h:4318:5: note:   template argument deduction/substitution failed:
8 : <source>:8:76: note:   could not resolve address from overloaded function 'addressof<double>'
     std::transform(t1.begin(), t1.end(), t2.begin(), std::addressof<double>);
                                                                            ^
Compiler exited with result code 1

However, I can't quite figure out why it is not working.

Thanks in advance to anyone trying to help :)

hassec
  • 686
  • 4
  • 18
  • 1
    Please be more specific than "fails" and "doesn't like it". Include verbatim error messages. – molbdnilo Aug 14 '17 at 08:37
  • 1
    `addressof` takes a variable name instead of a type name – meowgoesthedog Aug 14 '17 at 08:38
  • sorry, I thought it's easier to look at it in godbolt, but I guess you are right that it makes sense to have them here as well, so I added them ;) | And @meowgoesthedog not sure what you mean, the variable gets passed to the function via transform and one only needs to specify the template parameter right? – hassec Aug 14 '17 at 08:41
  • What happens when you store the function in a local first? auto f = std::addressof; – Serve Laurijssen Aug 14 '17 at 09:00

1 Answers1

9

To avoid accidentally taking the address of temporaries, the library has gotten a second (deleted) signature for addressof:

template <class T> constexpr T* addressof(T& r) noexcept;
template <class T> const T* addressof(const T&& elem) = delete;

See http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2598

So now the compiler doesn't know if your code should match the deleted function or not...

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • Oh wow, I somehow assumed that these deleted overloads won't take part in the overload resolution... Thanks a lot for the answer! That means I have no other option than wrapping that call in a lambda, right? – hassec Aug 14 '17 at 08:58
  • 1
    @Christoph deleted overloads exist specifically to participate in overload resolution and give a compile-time error for every function call which would be resolved to them. Otherwise they would be completely useless. – Revolver_Ocelot Aug 14 '17 at 09:03
  • @Revolver_Ocelot thanks for the explanation :) That makes complete sense to me, I guess I never consciously made that connection :P – hassec Aug 14 '17 at 09:04
  • 2
    @Christoph also, aside from wrapping call in lambda, you can specifically tell which overload to use by converting to pointer to function with specified signature: https://godbolt.org/g/UshjQS – Revolver_Ocelot Aug 14 '17 at 09:07