Is There a Indirection Functor?
Asked Answered
A

1

7

I'm looking for a unary functor which will dereference it's argument and return the result. Of course I can write one, it just seemed like something should already exist.

So given the code:

const auto vals = { 0, 1, 2, 3 };
vector<const int*> test(size(vals), nullptr);

iota(begin(test), end(test), data(vals));

transform(cbegin(test), cend(test), ostream_iterator<int>(cout, " "), [](const auto& i){ return *i; });

Live Example

I was hoping that there was a functor that I could use instead of the lambda. Does such a thing exist, or do I need to just use the lambda?

Anagrammatize answered 5/1, 2017 at 14:15 Comment(2)
I found very probable answer on why the functionality wasn't added to std hereIntrusion
@Intrusion It's interesting, I actually read through that post before asking the question. The example I've given is an MCVE, my actual use case for this is a vector<vector<int>::const_iterator> :(Anagrammatize
E
9

Assuming that by "functor" you mean "function object" or "callable object", there doesn't seem to be what you desire in the Standard Library.

It is trivial to implement it yourself:

struct deferencer
{
    template <typename T>
    decltype(auto) operator()(T&& x) const
        noexcept(noexcept(*x))
    { 
        return *x; 
    }
};

Note that your lambda doesn't do what you expect, as its implicit return type is -> auto, which makes a copy. One possible correct lambda is:

[](const auto& i) -> decltype(auto) { return *i; }

If you don't specify an explicit trailing return type for a lambda, the implicit one will be auto which is always a copy. It doesn't matter if operator* returns a reference, since the lambda returns a copy (i.e. the reference returned by operator* is then copied by the lambda's return statement).

struct A
{
    A() = default;
    A(const A&) { puts("copy ctor\n"); }
};

int main()
{
    []{ return *(new A); }(); // prints "copy ctor"
}

wandbox example

Ethylene answered 5/1, 2017 at 14:21 Comment(14)
I would use decltype(auto) so it also works for InputIterators that return proxy objectsPipit
@JonathanWakely: good point, updating the code to make it more general.Ethylene
@JonathanWakley What am I missing here? I thought the built-in indirection operator returned a reference to the value. Why would this be returning by value?Anagrammatize
@JonathanMee: operator* can be overloaded to return something that's not a reference. It could be useful if you want to return something that looks like a reference but is actually a proxy object.Ethylene
@VittorioRomeo Fair enough, but I believe this statement is in error: "Your lambda doesn't do what you expect, as its implicit return type is -> auto, which makes a copy." As I understand it, in the general case it should return a by reference, because for non-overloaded indirection operators the return type is a reference.Anagrammatize
@JonathanMee: if you don't specify an explicit trailing return type for a lambda, the implicit one will be auto which is always a copy. It doesn't matter if operator* returns a reference, since the lambda returns a copy (i.e. the reference returned by operator* is then copied by the lambda's return statement). wandbox exampleEthylene
@VittorioRomeo "error: expected unqualified-id before '=' token" doesn't seem like a great way to prove your point?Anagrammatize
@JonathanMee: come on, just give the lambda a name - I shared the wrong version of the code. Fixing...Ethylene
@VittorioRomeo Well before I refreshed the page, I'd typed up a question on why the return of a lambda was copying. If you want to elaborate on why, "the implicit one will be auto which is always a copy." I'd appreciate you doing so here: https://mcmap.net/q/1621095/-i-39-m-returning-a-reference-from-a-lambda-why-is-a-copy-happening-duplicate/2642059Anagrammatize
@JonathanMee: my remark about the return type of the lambda was not really related to the original question. I just wanted to make you notice a potential error in your code/understanding of the language. As you can see, the question has already been asked and properly answered in the past.Ethylene
@VittorioRomeo Yup, and I appreciated you pointing it out to me. I simply didn't understand.Anagrammatize
@JonathanWakely So how does decltype(auto) get translated as int& when auto would have stripped the reference?Anagrammatize
See auto, (5), which directs you to the rules for decltype. In short, decltype(x) preserves the "referenceness" of the x expression.Ethylene
@JonathanMee because that's what decltype(auto) means.Pipit

© 2022 - 2024 — McMap. All rights reserved.