std::optional::transform with std::addressof
Asked Answered
P

1

6

Consider the following code:

#include <memory>
#include <optional>

template <typename T>
constexpr T * arg_to_pointer(T & arg) noexcept {
    return std::addressof(arg);
}

int main() {
    std::optional<int> foo;

    auto * test = foo.transform(arg_to_pointer<int>).value_or(nullptr);
    //auto * test = foo.transform(std::addressof<int>).value_or(nullptr);

    return 0;
}

The line that is not commented out (that passes a dumb wrapper around std::addressof as the function parameter to std::optional::transform) compiles and works just fine. The line that is commented out (the one that tries to use std::addressof directly) does not - I get an error indicating that template argument deduction failed (live example here using GCC 13.2, though similar behavior is observed with Clang 16.0). Why is this? What is the difference between the standard std::addressof and my dumb wrapper around it?

Peggypegma answered 24/8, 2023 at 14:36 Comment(6)
std::addressof has overloads...Petal
Does it though? That link says there is one version until C++17, and another since C++17. There is an explicitly deleted overload since C++17 as well - but it isn't clear to me why that should make a difference. I have explicitly copied the C++17 and on version for my function signaturePeggypegma
If you add template <typename T> constexpr T * arg_to_pointer(T&&) noexcept /*=delete*/;, you would add similar issue.Petal
Indeed you do - just tried that myself. So I guess my question is now: Why? Why does explicitly deleting an overload make something more ambiguous? Surely I have made it less ambiguous by telling you it can't be that overload?Peggypegma
Overload resolution is "independant" of the definition of such overload.Petal
@RK - A deleted overload doesn't go away, but makes it an error if that overload is selected. So there are still two overloads, and T=int is not enough to tell them apart.Chirk
P
7

std::addressof has overloads...

One for lvalue (since C++11), and one for rvalue (since C++17), so std::addressof<int> is ambiguous. (even if it would be surprising to take the deleted overload ;-) ).

Anyway, std::addressof is not a addressable function.

Petal answered 24/8, 2023 at 14:46 Comment(1)
Had not realized the addressable function constraint. Thanks for thatPeggypegma

© 2022 - 2024 — McMap. All rights reserved.