0

I have chained methods like that:

PureCommand Hasher::nameToPure(CommandName& commandName) {
    return this->commandHash.find(commandName).value();
}
ByteCommand Hasher::nameToByte(CommandName& commandName) {
    return this->pureToByte(this->nameToPure(commandName));
}

The 2nd method is passing commandName which is wrong type as the 1st method needs reference, not an object. Then I've tried this:

ByteCommand Hasher::nameToByte(CommandName& commandName) {
    return this->pureToByte(this->nameToPure(*&commandName));
}

as stated here: How to cast/convert pointer to reference in C++ - because &commandName gives me pointer... but it's passing an object again. What am I doing the silly way? As probably it's something trivial...

Community
  • 1
  • 1
smsware
  • 429
  • 1
  • 13
  • 41
  • 1
    If you don't need to modify `commandName`, then pass it by const-ref (`CommandName const& commandName`). This will also solve this problem as far as I can see. – dyp Apr 06 '14 at 18:18
  • 1
    If you pass by non-const reference compiler implies you may modify the passed in object, and so requires it to be an lvalue. Meaning you have to create a temporary, which might become modified by subsequent call. – berkus Apr 06 '14 at 18:22
  • @dyp it worked. My I ask WHY? Actually, I need to modify it in one function but I've worked my way around it. Thanks. :) – smsware Apr 06 '14 at 18:23
  • How is `pureToByte` declared? I suspect that might be the actual problem. – aschepler Apr 06 '14 at 18:29
  • @aschepler pureToByte is declated really bad as it's leaking but I will solve this later ;-) ByteCommand Hasher::pureToByte(PureCommand const& pureCommand) { ByteCommand* byteCommand = new ByteCommand; for (HexByte h : pureCommand) { byteCommand->append(h); } return *byteCommand; } – smsware Apr 06 '14 at 18:31
  • 1
    @smsware A non-const lvalue reference cannot bind to an rvalue. If `pureToByte` takes a `CommandName&` <- that's the non-const lvalue ref; `this->nameToPure(..)` return by value <- there's the rvalue. Binding an rvalue to a const lvalue reference is allowed. The reason is that a non-const modifiable lvalue reference parameter *is an out-parameter*, and when you pass a temporary, you'll lose those modifications (since rvalues are typically temporaries). – dyp Apr 06 '14 at 18:54
  • @dyp thank you for clarify. :) – smsware Apr 06 '14 at 22:06

2 Answers2

2

There is nothing wrong with the original code. A reference can bind to an object.

(And in fact, no expression ever has a reference type. Expressions can be lvalues, xvalues, or prvalues, and commandName here is an lvalue, so an lvalue reference can bind to it.)

aschepler
  • 70,891
  • 9
  • 107
  • 161
  • It may be nothing wrong there but my complier disagrees as it's returning error that an object is not a reference (no matching function). I needed to create const references as @dyp suggested. – smsware Apr 06 '14 at 18:27
  • error: no matching function for call to 'Hasher::pureToName(PureCommand)'- candidate is: 'Hasher::pureToName(PureCommand&)' – smsware Apr 06 '14 at 18:35
  • Your post doesn't mention `pureToName` at all. – aschepler Apr 06 '14 at 18:39
  • sorry, copied the wrong one, it's the same error for every method. – smsware Apr 06 '14 at 18:41
  • sorry again, I can see what I did now... I mass changed everything to const& and it solved the problem but there were so many errors I've must have copied the wrong one to the original question as I can't really recreate the situation from before (I changed a lot on the way)... – smsware Apr 06 '14 at 18:46
2

Your code has no problem. But you should instead pass the const reference, Since you are not really modifying the value of commandName.

 PureCommand Hasher::nameToPure(const CommandName& commandName) {
    return this->commandHash.find(commandName).value();
}
ByteCommand Hasher::nameToByte(const CommandName& commandName) {
    return this->pureToByte(this->nameToPure(commandName));
}