I have been advised that value(x) is preferable to using x.value, but this can cause issues with uninitialized variables when trying to store variable values like:
initial_vals = {id(v): value(v) for v in m.component_data_objects(ctype=Var)}
If any of the variables are not initialized, then this will cause a ValueError to be raised. Is this a credible use case for x.value, or is there a suggested alternative using value(x)?
You can pass exception=False to the value function or the __call__ method on NumericValue objects. This will suppress the ValueError and just return None.
On the other hand, if you know it's a variable, then it is absolutely safe to use the .value attribute. Params are the only other object (that I know of) with a .value attribute, but there is so much variation in how indexed Params can behave that it becomes preferable to just use the value function.
Related
In C++ the indexing operator is defined for std::map and std::unordered_map so that if your reference to the container is non-const just the act of indexing without assigning is enough to have implicitly created a value inside the container. This sometimes creates subtle bugs, where you expect to be referencing a value inside a container but instead actually create one, e.g. config["stting"] instead of config["setting"].
I know Python addresses this by having __setitem__ and __getitem__ be separate methods but this requires cooperation with the parser.
Does Rust do anything to address this frequent source of bugs?
No Rust doesn't have that problem. There's no implicit creation of items in Rust collections.
For example you'd insert a key-value pair to a std::collections::HashMap with map.insert(key, value) and retrieve a value with let value = map.get(key);.
Note that .get() will return an Option<&V>, so if the key didn't exist you will get None as a result.
Rust also offers an easy way to either retrieve a value or to insert some default value for the given key if the value doesn't exist with:
let value = map.entry(key).or_insert(0);
HashMap also implements the Index trait, which allows retrieval of a value with let value = map[key];, which will panic if key doesn't exist in map.
Note that because HashMap does not implement IndexMut, this [ ] bracket syntax always returns an immutable reference to the value, so you cannot insert or modify values this way.
My requirement is to parse on XML and populate an object. How do I automatically track if attribute xyz is present once the object is populated from the Xml. Please note that I will no longer have access to the parsed buffer after the object is populated. Hence I need some mechanism to know whether the attribute was present in XML and the same is populated in the object.
I have the below solution in my mind but not sure if anything more efficient possible. Also I am looking for a generic solution for this problem.
define a bit for each of the attribute in a class.
setter function should set that bit while parsing XML when attribute is present
getter function should check the bit before returning the attribute value by reference argument . It should return false when bit is not set. ( The getter function return type should be boolean and it accepts one argument which is of type attribute and populate it when present)
From your comment I gather that you can change the design, so this is what I would do:
Replace all optional members with the aptly-named std::optional or the boost equivalent if the former is not available.
using std::optional; // facilitates easy switching between std and boost if needed
class MyClass {
optional<int> some_value;
// Similarly for rest of attributes
void set_some_value(int value_to_store) { some_value = value_to_store; }
optional<int> get_some_value() { return some_value; }
}
To read from it do as follows
MyClass instance;
// ... parse XML and set attributes
auto some_value = instance.get_some_value;
if (some_value) {
do_something_with_int(*some_value);
}
Some notes on optional:
Default-constructed optionals are empty. This means that every attribute you don't explicitly set is empty by default.
Dereferencing an empty optional is undefined behavior. There are safer ways to access it. In this example it is safe because we manually checked for it since I assume you'd like to branch on the existence of your attribute anyway.
The managed object is guaranteed to be inside the allocated optional object. This means no dynamic allocation which is great for speed. If you have any huge objects, however, this can cause stack overflow issues. It's not likely, though, as most real world scenarios of large objects are using a string or some STL container/wrapper that holds its data on the heap anyway.
I couldn't find a mention of the space cost in the standard. I believe it is typically implemented with a single bool inside every optional object. sizeof(bool) is often sizeof(int). This makes it more space consuming than necessary, but it's as fast as possible. This is generally a good trade-off, but if you encounter memory usage problems and you have a lot of objects holding optionals you might need to find a more space-optimal solution. If you can use sentinel values to signal non-existence, look up implementations of compact optional objects.
I have a function with the following header:
std::vector<NxU32> MySewer::createCuttingArray(MyCloth** cloth, NxU32 startPoint, NxU32 endPoint)
The function is supposed to return a vector containing some integer values. But there is one problem: If the line is not correctly created (there is a way in which this can happen), I want to do something like what I did in Java and C#, to return a NULL. But from what I see, in C++, NULL is defined as an integer value. How can I return a valid NULL for a vector?
The "correct" way to deal with this really depends on what the code receiving the vector actually does. Is it cause for an error, or simply "we ignore this"?
If it's an error, use throw some_exception_goes_here;, because that is much easier than going down the line with a NULL value.
If you want to just ignore it, return an empty vector and then make sure the code below isn't going to have problems with an empty vector.
By your description, what you want is boost::optional<std::vector<NxU32>>.
I hope the name makes its intent obvious.
http://www.boost.org/doc/libs/release/libs/optional/doc/html/index.html
I don't think there is a need for any boost::optional nor std::exception. What you should return is an empty vector. Think about it. The function returns a list of integers and the function caller operates on the list of integers. If the list is empty, then there is nothing to operator on. For example( in psuedo)
std::vector<T> data = createData(args);
for(int i = 0; i < data.size(); ++i){
calculate(data[i]);
}
That for loop isn't going to execute if the data is empty. There is no need for null checks or exception handling.
boost::optional<T> addresses this problem by extending a type T to be a type that can either "have a value of type T" or "not have a value." In your case, you would be returning a boost::optional<std::vector<NxU32>> because you want to, in some cases, return "nothing."
The boost documentation has some examples here.
This functionality seems basic enough that you might expect it to be part of the standard library. Sadly, it isn't (yet). See related: boost::optional alternative in C++ Standard Library
You can't. To emulate the behaviour of reference types in .NET, of which variables can be either attached to an actual object or be null, you need to use pointers in C++. Pointers can be either NULL or point to a valid object.
On balance, I think I'd change the pattern. Create the vector in the caller, pass as a reference (or pointer) into your function and have a bool return true / false indicating success or failure.
Doing it this way also means you're not invoking the std::vector<> copy constructor on the return value.
If you already have boost installed and up and running I'd be tempted to return boost::optional as other answers indicate. But note that getting boost to work can be a headache, (it has its own build environment which is a learning curve) especially if you're using StlPort.
You just can't do that in C++.
You are returning a vector that will be copied (and instantiated among other things). Other thing is that you can't cast something that isn't a vector to NULL.
I read in data from an XML file, depending on the tags in the xml file, data gets attached to class member variables.
Is it possible if for example a value in the xml file contains "!", which in this case is not valid thus I can't accept that value.
So the member variable for that value is empty.
But the type of some member variables are other classes or integers or boolean. How can I check if those values are set? As there is no function emtpy() for those.
If they are not optional, you must cause your parsing mechanism to error when they are not present. Else, you could use something like boost::optional.
There is no way to detect at run time, whether a variable has been explicitly set. That's why some compilers give you a warning (not an error), if they suspect that a variable might be used uninitialized.
It is the programmer's responsibility, to keep track of what variables have been set. The low level way to do this, is to use pointers, initialize them to 0, change them when they should point to some initialized memory and change them back to 0 when the object they point to is deleted.
In C++, you can use Boost.Optional to spare you from messing around with pointers in this way.
you could during XML read, check the XML value and if it contains "!", assign a default value to whatever variable it is.
e.g. set ptr to nullptr, boolean to false and int to 0 or -1.
Use const default values whenever you can, that will make your code clearer and easier to maintain.
let's say I want my users to use only one class, say SpecialData.
Now, this data class would have many methods, and depending on the type of data, the methods do different things, internally, but return externally similar results. Therefore my wanting to have one "public" class and other "private", child classes that would change the behavior of methods, etc...
It would be amazingly more simple for some types of data that need to be built to do something like this:
SpecialData& sm = SpecialData::new_supermatrix();
and new_supermatrix() would return a SuperMatrix instance, which inherits from most behaviors of SpecialData.
my header:
static SpecialData& new_supermatrix();
my cpp:
SpecialData& SpecialData::new_supermatrix()(){
return SuperMatrix(MATRIX_DEFAULT_MAGNITUDE,1000,1239,FLOAT32,etc...);
}
The problem is, I get this error, which is probably logical due to the circumstances:
invalid initialization of non-const reference of type ‘SpecialData&’ from a temporary of type ‘SpecialData’
So, any ideas?
Well, you've got three choices:
a) You want to have only one instance of SuperMatrix anyway. Then go for the static function member route as has already been suggested.
b) You want to create multiple instances. Then you have to return a pointer instead of references and create the objects with with new (i.e. return new SuperMatrix(...).
c) As an alternative to option b, you can also return merely an object, i.e.
SpecialData SpecialData::new_supermatrix()(){
return SuperMatrix(MATRIX_DEFAULT_MAGNITUDE,1000,1239,FLOAT32,etc...);
}
However, this requires a (deep-)copy operator (the default one won't suffice more often than not), and it means that the object is created on the stack, then copied and that copy is being returned. The good thing is, this won't leak memory if you don't actually receive the result into a variable. The bad thing is, if the object is very large, this can be very memory- and time-consuming.
Whatever you are going to do with it, these solutions are mutually exclusive, both technically and logically. ;)
Simple answer - you can't use references like that. Your new_supermatrix function returns a nameless temporary value which you try to bind to a non-const reference - C++ only allows such values to be bound to const references. If you want to write functions like this, you need to make them return a pointer to a dynamically allocated object, or stick with returning a value, but assign the return value to another value in the calling code.
This code has several problems. First of all, you probably want to use pointers here instead of references. Returning a reference to an object created on the stack like you do in your new_supermatrix will lead to a crash almost immediately. It needs to be allocated with new and passed back as a pointer if that's what you want but I'm not exactly sure what you're trying to do. But anyway, this is what's causing your error, you're returning a reference to a temporary variable.
You need to actually use the new operator. The creation you get by return SuperMatrix(MATRIX_DEFAULT_MAGNITUDE,1000,1239,FLOAT32,etc...); allocates the object on the stack, which is cleaned up when the function returns (which it is doing in the same line). Using new causes it to be allocated on the heap.
In your method, you can use a static:
SpecialData& SpecialData::new_supermatrix()(){
static SuperMatrix supermatrix(MATRIX_DEFAULT_MAGNITUDE,1000,1239,FLOAT32,etc...);
return supermatrix;
}
You must not return a reference to a temporary/local object.
This and many other common errors-to-be-avoided are explained in Meyers' book, Effective C++.
You're returning a reference to a temporary object, which is bad news, since once your method exits, the object doesn't exist anymore.
Read up on creational design patterns. The one that looks closest to what you want to do is the Factory Method pattern.