Open GiulioRomualdi opened 3 years ago
I just noticed that the error appears also with this simple code
#include <string>
#include <iostream>
#include <yarp/os/Value.h>
#include <yarp/os/Bottle.h>
int main(int argc, char **argv) {
bool parameter = true;
yarp::os::Value value = yarp::os::Value(parameter);
if (!value.isBool())
{
std::cerr << "The value is not a boolean." << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
};
Am I doing something wrong?
Accordingly to the documentation, seems there is no way to pass a bool
in a Value
. Probably the boolean is implicit converted in a int
and this constructor is called
However, now I don't understand when isBool()
should return true
It is only true
if we store a vocab that is either 0
or equal to '1'
(ASCII -> 49): ref.
Hi @PeterBowman, thank you for the response.
Accordingly to your suggestion I modified the code as follows
#include <string>
#include <iostream>
#include <yarp/os/Value.h>
#include <yarp/os/Bottle.h>
int main(int argc, char **argv) {
yarp::os::Value value = yarp::os::Value('1');
if (!value.isBool())
{
std::cerr << "The value is not a boolean." << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
};
however, the error is still there.
According to docs, you must pass a second parameter so that the first one is interpreted as a vocab, namely Value('1', true)
. In any case, I don't think this can be used to reliably store (or pretend to store) a Boolean Value. Ideally, another constructor would be added for proper Boolean support, and a StoreBool
be derived from Storable
(see inheritance diagram).
If I remember correctly I tried some time ago, but adding a StoreBool
and proper methods that accept bool would cause conflicts in the API and in the bottle serialization protocol...
The problem is that at the moment, as @PeterBowman mentioned, a "bool" is a Vocab, that is either 0
or 49
(0x31
, i.e. the '1'
character). This is probably nonsense, but there is code relying on that.
Note that there is also a lot of code that uses VOCAB_OK
and VOCAB_FAIL
as boolean, see for example https://github.com/robotology/yarp/blob/10dc2b5fb6223871b06d67110ac22ba3ea44ad6a/src/libYARP_os/src/yarp/os/idl/WireWriter.cpp#L75-L80
and https://github.com/robotology/yarp/blob/10dc2b5fb6223871b06d67110ac22ba3ea44ad6a/src/libYARP_os/src/yarp/os/idl/WireReader.cpp#L101-L119
as a consequence, all idl generated classes use this convention.
This is quite confusing in my opinion, but that's not something we can fix without breaking code, and all binary protocols.
The problem is that at the moment, as @PeterBowman mentioned, a "bool" is a Vocab, that is either
0
or49
(0x31
, i.e. the'1'
character). This is probably nonsense, but there is code relying on that.
For further reference, a 0
vocab is interpreted as Boolean false
and '1'
as Boolean true
(ref). Conversely, a "true"
or "false"
string is parsed as Boolean by the internal Bottle mechanisms if properly triggered, i.e. via Bottle constructor or Property's fromString
or Value's makeValue
or similar (but not via Value(const std::string&)
). In other words, this interpretation is hardcoded in such a way that passing --opt true
or --opt false
(while reading from .ini file or using the command line) will make isBool()
evaluate to true
on opt
because of the implicit/transparent conversion to a vocab via string parsing under the hood.
@GiulioRomualdi knowing this fact, you can overcome this limitation with strings:
auto * v = yarp::os::Value::makeValue("true"); // or "false"
std::cout << v->isBool() << "\n"; // true
delete v; // sadly, `makeXXX()` static methods return unmanaged raw pointers
Alternatively:
yarp::os::Bottle b("true"); // or "false"
std::cout << b.get(0).isBool() << "\n"; // true
In your first example:
// we invoke `add(Value*)` here instead of `add(const Value&)`, dynamic memory is owned by the containing Bottle
list->add(yarp::os::Value::makeValue("true")); // note `makeValue` only accepts strings
Or just:
yarp::os::Bottle container("(flag true)");
Hi @PeterBowman and @drdanz thank you for your suggestions I will go for
list->add(yarp::os::Value::makeValue("true")); // note `makeValue` only accepts strings
Describe the bug I'm trying to store several
yarp::os::Value
inside ayarp::os::Bottle
. Before retrieving the object I check the type of the object. When the object stored inyarp::os::Values
is booleanyarp::os::Value::isBool()
returns false.To Reproduce
The
cpp
code followsThe application prints
Expected behavior
value->isBool()
should return trueConfiguration (please complete the following information):