boost::any confusion with pointers vs values - c++

It took me a while to figure this out, but the semantics of boost::any are confusing.
With value types, you use it like so:
int value = 100;
boost::any something;
something = value;
//...later...
int value = boost::any_cast<int>(&something);
This code is clear and makes sense, but stores value internally as a copy. This means for larger objects I place inside boost::any, they will be copied. Also any functions that I replace void* with this will expect that the value outside the function is modified when I modify the value contained in the boost::any object (which won't happen, since it copied it).
So if I put pointers into it, things get weird:
int value = 100;
boost::any something;
something = &value;
//...later...
int* value = *boost::any_cast<int*>(&something);
I have to dereference the return value in this case because boost::any_cast returns int**! I also haven't checked but I think this may crash if something.empty() == true. This is just not straightforward at all.
I do not want to store values in my boost::any, I want it to only function on pointers and behave semantically closer to void*. Pointers in, pointers out, with some type-safety mixed in. Essentially what I want is boost::any_pointer, or something like that. Is there a way to prohibit boost::any from accepting anything except pointers? And if not, is there an alternative to boost::any that can give me the semantics I'm looking for?

You are using any_cast wrong:
There are essentially two (three) flavors.
Taking a reference to any and returning a value or reference to the content
Taking a pointer to any and returning a pointer to the content
Examples:
#include <boost/any.hpp>
int main()
{
// Any holding a value
{
boost::any any_value(1);
// Throws bad_any_cast if the content is not 'int' (in this case):
int value = boost::any_cast<int>(any_value);
// Throws bad_any_cast if the content is not 'int' (in this case):
int& reference = boost::any_cast<int&>(any_value);
// Returns a null pointer if the content is not 'int' (in this case):
int* pointer = boost::any_cast<int>(&any_value);
}
// Any holding a pointer (which is nothing else but a value)
{
int integer = 0;
boost::any any_ptr(&integer);
// Throws bad_any_cast if the content is not 'int*' (in this case):
int * pointer = boost::any_cast<int*>(any_ptr);
// Throws bad_any_cast if the content is not 'int*' (in this case):
int*& pointer_reference = boost::any_cast<int*&>(any_ptr);
// Returns a null pointer if the content is not 'int*' (in this case):
int** pointer_pointer = boost::any_cast<int*>(&any_ptr);
}
}
See also: http://en.cppreference.com/w/cpp/experimental/any and http://en.cppreference.com/w/cpp/experimental/any/any_cast

NOTE: I am assuming you want to store pointers in boost::any, since you are looking for something on the lines of boost::any_pointer (though non-existent).
boost::any_cast returns the pointer to the actual value stored inside it (the held object inside holder). So it kind of saves a copy unless you actually want to copy it later.
template<typename ValueType>
ValueType * any_cast(any * operand) BOOST_NOEXCEPT
{
return operand && operand->type() == boost::typeindex::type_id<ValueType>()
? &static_cast<any::holder<BOOST_DEDUCED_TYPENAME remove_cv<ValueType>::type> *>(operand->content)->held
: 0;
}
You can always create a wrapper around boost::any to allow only pointer types:
class MyAny {
public:
template <typename T,
typename = typename std::enable_if<std::is_pointer<std::remove_cv<T>::type>::value>::type>
MyAny(T ptr): any_(ptr) {}
template <typename ValueType>
ValueType operator*() {
return *boost::any_cast<ValueType>(&any_);
}
private:
boost::any any_
};
Above is a rough code, I have not compiled and tested it.
std::enable_if type trait is available in C++11, but can be found in boost as well. It is what that will constrain your MyAny to only pointer types.

Although this is quite an old question, I nevertheless would like to point out a simple misconception [I think] in the preface of the asked questions:
int value = 100;
boost::any something;
something = &value; // 1)
//...later...
int* value = *boost::any_cast<int*>(&something); // 2)
1) This saved "int *" in something.
2) This contains essentially several steps:
"&something" gets the address of something, i.e. return "boost::any *"
"boost::any_cast()" now casts this address to a pointer to an int - which is probably not what void.pointer wanted. And I don't know whether - and if, why - this seems to work.
And then you dereference "*boost::..." this, i.e. cancelling the "&" from the first step again.
What I think, void.pointer wanted to do here, is more along the following line:
int* value = boost::any_cast<int*>(something);
.
PS: I would have liked to put this in a simple comment and not a full-fledged answer - stackoverflow however requires me to collect enough points first, so...

Related

How to tell if a pointer is the pointer to an array?

Consider this
template <class T>
inline constexpr bool found_to_be_array (T* specimen)
{
if constexpr (std::is_array_v<T>) {
return true;
}
else {
return false;
};
}
The question is in which context is this going to produce the reliable result?
Clarification: I can not change the footprint of this function. I have no answer, so let me post my findings here. Consider this:
int ia[]{ 1,2,3,4,5,6,7,8,9,0 };
int iam[3][3][3][3][3]{};
// returns false
auto is_array_1 = found_to_be_array(ia);
// returns true
auto is_array_2 = found_to_be_array(iam);
I am still researching this, but for multidimensional arrays, found_to_be_array works.
https://godbolt.org/g/ij73Z4
No this approach will not work. The parameter specimen has already decayed to a pointer type (or it might even have been a pointer all along); the metaprogramming technique used by std::is_array does not trace back in some way to the caller.
And besides, you're testing (unintentionally?) T rather than T* - but changing to the latter will not work.
How to tell if a pointer is the pointer to array?
A pointer has type, which indicates what it points to. When it points to array, then the type of the pointer reflects this, for example:
int arr[2][2] = {{1,2},{3,4}};
auto x = &arr[0];
x in this case has the type of int(*)[2]- a pointer to array of 2 ints, in this case {1,2}. If you increase this pointer by 1 it will point to the next array of 2 ints, namely {3,4}. If you pass this pointer to your function, T will be deduced as int[2] and the result will be true;
In case of 1D array it is no different:
int arr[4] = {1,2,3,4};
auto x = &arr;
x type will be int(*)[4] and it will also work and the function will return true.
But if you pass array to your function and not the pointer, thus forcing it to decay to the pointer to its 1st element, the array information is lost, because the pointer is of type int now.
auto x = arr;
x here is of type int *, it is not pointing to array, it points to the first int, which is 1. If you increase it by one it will point to the next int, which is 2 and so on. If this was a pointer to the array, it would point to the next byte after array end if you increase it by 1. Passing this pointer to your function would return false, because int type is not an array.
So to answer to your question, you can tell that the pointer is a pointer to array, because this information would be supplied in the pointer type.
int iam[3][3][3][3][3]{};
// returns true
auto is_array_2 = found_to_be_array(iam);
iam decays to the pointer to its 1st element, basically you are testing if iam[0] is an array, which it is, and so it works.
Whether a non-null data-pointer points to an array-element, is always answered maybe.
Why, you ask?
The language explicitly allows you to treat any object as the single element of an array of one. Which is quite nifty when you need a sequence, want to copy a trivial object, or the like.
Thus, every pointer is one of:
a null-pointer,
a pointer to an element of an array,
a pointer to beyond an element of an array, or
invalid, meaning one of
wild, meaning never initialized, or
dangling, meaning the pointee's lifetime was ended.
And while you can differentiate between case 1 and 2 or 3, the rest would need analysis of potentially the complete history of the current run of the program.
Your requirement that you can not change the function is weird/unreasonable.
If you can not change the function signature you can not detect how argument was produced(from ptr or array) because that information is lost.

C++ rvalue and pointer of pointer when should I use it?

Please consider these 2 lines of code
void doStuff(int ** i)
void doStuff2( int && i)
in the first one I assume that it is a pointer of pointer and the second is an rvalue,
I came across this question and it explains the rvalue but when should I use the first and when should I use the second ?
could you clarify this to me please ?
int ** i is a pointer to a pointer.
Generally, use this sparingly, as this may have different meanings and you have better ways to express that in C++.
It may be a pointer to single variable containing a pointer to a single int:
int value = 0;
int * pValue = &value;
int ** ppValue = &pValue;
However, each may also be a pointer to the first element of an array:
int valuesA[1000], valuesB[100], valuesC[10];
int * pValues[] = { valuesA, valuesB, valuesC };
// these are actually pointers to the first element of the array
int ** ppValues = pValues;
Use this only with clear documentation how to access elements, how to know the element sizes, and who is responsible for freeing (if any), how long the pointers are valid etc.
Usually, if you have such an array / matrix, you certainly should wrap it behind a safe-to-use interface, or replace it alltogether e.g. with a vector<vector<int>>.
Even for the single-int use cases there are usually better options. E.g. a function signature that allows to modify a pointer, a reference to a pointer would be more suitable:
bool SelectValue(int *& p) { ... }
int && is a rvalue reference.
Unlike the int **, this is not a double indirection.
It is, roughly a reference that can also bind to a temporary value.
("Normal" references cannot).
A Brief Introduction to Rvalue References

Casting a pointer by reference

I came across something I don't understand well. Let's suppose I want to pass a character pointer to a function that takes a reference to a void pointer.
void doStuff(void*& buffer)
{
// do something
}
I would usually do something like this :
int main()
{
unsigned char* buffer = 0;
void* b = reinterpret_cast<void *>(buffer);
doStuff(b);
return 0;
}
Why it is not possible to directly pass the reinterpret_cast to the function?
int main()
{
unsigned char* buffer = 0
// This generate a compilation error.
doStuff(reinterpret_cast<void *>(buffer));
// This would be fine.
doStuff(reinterpret_cast<void *&>(buffer));
return 0;
}
There must be a good reason behind this behavior but I don't see it.
In the first example, you're actually passing the pointer variable b. So it works.
In the second example, the first reinterpret_cast returns a pointer (by value), which doesn't match the reference the function should get, while the second returns said reference.
As an example to show you how references work, look at these two functions,
void doSomething( unsigned char *ptr );
void doSomethingRef( unsigned char *&ptr );
Say we have this pointer,
unsigned char *a;
Both functions are called the same way,
doSomething( a ); // Passing pointer a by value
doSomethingRef( a );// Passing pointer a by reference
Though it may look like you're passing it by value, but the function takes a reference so it will be passed as a reference.
A reference is similar to a pointer but it has to be initialized with a left value and can't be null.
Having said that, there are much better alternatives to using void* and especially void*&. void* makes code harder to read and easier to shoot yourself in the foot (if anything by making yourself use these strange casts).
As I said in the comments, you could use a template and not bother with void casting.
template< class T > void doStuff( T *&buffer ) {
...
}
Or,
template< class T > T* doStuff( T* buffer ) {
...
}
EDIT: On a side note, your second example is missing a semicolon,
unsigned char* buffer = 0; // Right here
int main()
{
unsigned char* buffer = 0;
void* b = reinterpret_cast<void *>(buffer);
doStuff(b);
return 0;
}
b is a pointer and doStuff(b) is receiving the address of a pointer. The types match, b is of type void*& (*b is of type void*) and doStuff receives a parameter of type void*&.
int main()
{
unsigned char* buffer = 0
// This generate a compilation error.
doStuff(reinterpret_cast<void *>(buffer));
// This would be fine.
doStuff(reinterpret_cast<void *&>(buffer));
return 0;
}
The second call is like the the call from the above function with b as parameter.
The first call is passing simply a void pointer. The types are different, look closer void* is not the same as void*&
This is how you would specify a reinterpret_cast as the function argument directly, without using an intermediate variable. As others have told you, it's bad practice, but I want to answer your original question. This is for educational purposes only, of course!
#include <iostream>
void doStuff(void*& buffer) {
static const int count = 4;
buffer = static_cast<void*>(static_cast<char*>(buffer) + count);
}
int main() {
char str[] = "0123456789";
char* ptr = str;
std::cout << "Before: '" << ptr << "'\n";
doStuff(*reinterpret_cast<void**>(&ptr)); // <== Here's the Magic!
std::cout << "After: '" << ptr << "'\n";
}
Here we have a pointer to char named ptr and we want to wrangle its type to void*& (a reference to a void pointer), suitable for passing as an argument to function doStuff.
Although references are implemented like pointers, they are semantically more like transparent aliases for another value, so the language doesn't provide the kind of flexibility you get for manipulating pointers.
The trick is: a dereferenced pointer converts directly into a correspondingly typed reference.
So to get a reference to a pointer, we start with a pointer to a pointer:
&ptr (char** - a pointer to a pointer to char)
Now the magic of reinterpret_cast brings us closer to our goal:
reinterpret_cast<void**>(&ptr) (now void** - a pointer to a void pointer)
Finally add the dereferencing operator and our masquerade is complete:
*reinterpret_cast<void**>(&ptr) (void*& - a reference to a void pointer)
This compiles fine in Visual Studio 2013. Here is what the program spits out:
Before: '0123456789'
After: '456789'
The doStuff function successfully advanced ptr by 4 characters, where ptr is a char*, passed by reference as a reinterpret_cast void*.
Obviously, one reason this demonstration works is because doStuff casts the pointer back to a char* to get the updated value. In real-world implementations, all pointers have the same size, so you can probably still get away with this kind of manipulation while switching between types.
But, if you start manipulating pointed-to values using reinterpreted pointers, all kinds of badness can happen. You will also probably be in violation of the "strict aliasing" rule then, so you might as well just change your name to Mister Undefined Behavior and join the circus. Freak.
I'm not sure if this is right, but...
I believe it's as simple matching the argument type:
void doStuff(void* buffer) {
std::cout << reinterpret_cast<char*>(buffer) << std::endl;
return;
}
You could do the above and the int main() would compile correctly.
A reference is different from a copy of a value--the difference is that the copied value doesn't necessarily need to live in a variable or in a place in memory--a copied value could be just a stack variable while a reference shouldn't be able to point to an expiring value. This becomes important once you start playing around with reference and value semantics.
tl;dr: Don't mix references and values when casting. Doing operations on a reference is different than doing operations on a value; even if argument substitution is implicitly casted.

C++ type casting with pointers

I come from a background of C# and Java and I can't seem to understand what casting with pointers means in C++.
For example:
int x = 1;
char c = *((char*)&x);
What does it do? What it is useful for?
In both your examples you're making mistakes making the code not compile. So I'll assume you're trying to do the following:
int x = 1;
char c = *((char*)&x);
Depending on your architecture, c will now have either the value of the least or the most significant byte of x. In this example this would be either 0 or 1 (this can actually be used to detect the byte ordering).
Your second example won't work, cause you're trying to ignore the const resulting in an illegal operation/bad cast (this is also called "const correctness").
Edit: Regarding your comment about "what does it mean?":
In expressions:
&somevariable will return the address of somevariable.
*somevariable will assume the contents of somevariable are the address of the actual value, which is then returned.
In declarations:
datatype is a normal variable/object. This is passed "by value".
datatype& is a reference. This works exactly like normal variables in Java/C# and is passed by reference.
datatype* is a pointer. This just contains the address where the actual value is located (see above) and is essentially passed by reference as well.
Actual casts work pretty much similar to Java/C#, but pointers are just that: They point to the location of the actual value. While this might confuse you, pointers in C/C++ work pretty much like the standard variables/references used in Java/C#.
Look at this:
MyClass x; // object of MyClass
MyClass *x; // pointer to an object of MyClass - the actual value is undefined and trying to access it will most likely result in an access violation (due to reading somewhere random).
MyClass *x = 0; // same as above, but now the default value is defined and you're able to detect whether it's been set (accessing it would essentially be a "null reference exception"; but it's actually a null pointer).
MyClass &x = MyClass(); // creating a new reference pointing to an existing object. This would be Java's "MyClass x = new MyClass();"
Casting in C++ works just like casting in Java, no pointers involved.
int x = 1;
char c = (char) x; // Lose precision
However, what you are doing here:
int x = 1;
char *c = (char *)x;
is telling the compiler that the value of x is the address of a character. It is equivalent to
char *c;
c = 1; // Set the address of c to 0x0000000000000001
There are very few times you need to do this.
There are two fundamentally different concepts in C++ which are both sometimes referred to as "casting": One is conversion, and one is reinterpretation.
Conversion creates a new object with the "same value" as an existing object, but of a different type. Here are some examples:
Example 1: type promotion
// 1a: promote int to double to get the correct type of division
int numerator = rand(), denominator = rand();
double d = double(numerator) / double(denominator);
// 1b: convert int to double to achieve a particular argument deduction
int n;
template <typename T> void do_numeric_stuff(T x) { /* ... */ }
do_numeric_stuff(double(n));
Example 2: Derived-to-base conversion
struct B { }; struct D : B { };
D x;
D * p = &x; // pointer to x
B * q = p; // implicit conversion; may change the value!
On the other hand, reinterpretation allows us to treat one variable as though it was another one. About the only correct and useful application for this is serialization, in one form or another.
Example 3: Serialization
std::ofstream file("output.bin"); // output file
char large_buffer[HUGE]; // in-memory buffer
unsigned int n = get_data();
char const * p = reinterpret_cast<char const *>(&n);
file.write(p, p + sizeof n); // write the bytes of `n`
std::copy(p, p + sizeof n, large_buffer); // ditto
std::copy(large_buffer + 17, large_buffer + 17 + sizeof n,
reinterpret_cast<char *>(&n)); // repopulate `n` from buffer
The standard says that it is undefined behaviour to access an object through a pointer that is not of the correct type (also called "type punning"). While it is OK to store an object pointer in, say, a void* and then convert it back and use it, it is not OK to treat a float as though it was an integer, etc. The only acceptable way of accessing one object as though it was another is the one I demonstrated, namely treating an object of type T as though it was an array char[sizeof(T)] — that is, you are allowed to access the underlying binary representation of every object.
You should avoid c-type casts like (char*) by all means. If you really have to do a type cast have a look at dynamic_cast, static_cast and reinterpret_cast.
But as already stated, you rarely need casting at all.
Have a look here for fruther information:
http://www.cplusplus.com/doc/tutorial/typecasting/
http://www.parashift.com/c++-faq/static-typing-and-cpp.html
http://www.parashift.com/c++-faq-lite/print-char-or-ptr-as-number.html
I used many time ago that idiom to access HW at specified address, on custom IO board. So for instance to write at PIC (programmable interrupt controller) to reset some flag (fictious code):
#define PIC_LOC 0x1000
#define PIC_ENABLE_PORT *((char*)(PIC_LOC+0x10))
#define BIT_ENABLE (1 << 3)
...
PIC_ENABLE_PORT |= BIT_ENABLE;
...

const to Non-const Conversion in C++

I'm really annoyed by const keyword these days, as I'm not quite familiar with it. I had a vector that stores all const pointers like vector<const BoxT<T> *> *Q_exclude, and in the constructor of another class, I need an element in this queue to be passed in as a parameter and assign it to a non-const member. My question is:
How do I assign a const variable to a non-const variable? I know this doesn't make sense because after all, a const is a const, and should not be changed by any mean. But that annoying member variable REALLY has to be changed during the process! I might also change the data type in the vector to be non-const, but that would be too much work. Or does anyone know how to avoid such situation?
You can assign a const object to a non-const object just fine. Because you're copying and thus creating a new object, constness is not violated.
Like so:
int main() {
const int a = 3;
int b = a;
}
It's different if you want to obtain a pointer or reference to the original, const object:
int main() {
const int a = 3;
int& b = a; // or int* b = &a;
}
// error: invalid initialization of reference of type 'int&' from
// expression of type 'const int'
You can use const_cast to hack around the type safety if you really must, but recall that you're doing exactly that: getting rid of the type safety. It's still undefined to modify a through b in the below example:
int main() {
const int a = 3;
int& b = const_cast<int&>(a);
b = 3;
}
Although it compiles without errors, anything can happen including opening a black hole or transferring all your hard-earned savings into my bank account.
If you have arrived at what you think is a requirement to do this, I'd urgently revisit your design because something is very wrong with it.
Changing a constant type will lead to an Undefined Behavior.
However, if you have an originally non-const object which is pointed to by a pointer-to-const or referenced by a reference-to-const then you can use const_cast to get rid of that const-ness.
Casting away constness is considered evil and should not be avoided. You should consider changing the type of the pointers you use in vector to non-const if you want to modify the data through it.
The actual code to cast away the const-ness of your pointer would be:
BoxT<T> * nonConstObj = const_cast<BoxT<T> *>(constObj);
But note that this really is cheating. A better solution would either be to figure out why you want to modify a const object, and redesign your code so you don't have to.... or remove the const declaration from your vector, if it turns out you don't really want those items to be read-only after all.
Leaving this here for myself,
If I get this error, I probably used const char* when I should be using char* const.
This makes the pointer constant, and not the contents of the string.
const char* const makes it so the value and the pointer is constant also.
void SomeClass::changeASettingAndCallAFunction() const {
someSetting = 0; //Can't do this
someFunctionThatUsesTheSetting();
}
Another solution is to call said function in-between making edits to variables that the const function uses. This idea was what solved my problem being as I was not inclined to change the signature of the function and had to use the "changeASettingAndCallAFunction" method as a mediator:
When you call the function you can first make edits to the setting before the call, or (if you aren't inclined to mess with the invoking place) perhaps call the function where you need the change to the variable to be propagated (like in my case).
void SomeClass::someFunctionThatUsesTheSetting() const {
//We really don't want to touch this functions implementation
ClassUsesSetting* classUsesSetting = ClassUsesSetting::PropagateAcrossClass(someSetting);
/*
Do important stuff
*/
}
void SomeClass::changeASettingAndCallAFunction() const {
someFunctionThatUsesTheSetting();
/*
Have to do this
*/
}
void SomeClass::nonConstInvoker(){
someSetting = 0;
changeASettingAndCallAFunction();
}
Now, when some reference to "someFunctionThatUsesTheSetting" is invoked, it will invoke with the change to someSetting.