The following piece of code:
typedef void* ptr_t;
void func()
{
const ptr_t ptr; // Line 1
ptr = ...; // Line 2
}
Yields the following compilation errors:
Line 1, Error C2734 (C++): const object must be initialized if not extern
Line 2, Error C3892 (C++): you cannot assign to a variable that is const
Line 2, Error C2166 (C): l-value specifies const object
The reason behind these compilation errors:
const ptr_t ptr is interpreted as void* const ptr instead of const void* ptr
With void* const ptr, you cannot change the pointer but you can change the pointed data
With const void* ptr, you can change the pointer but you cannot change the pointed data
My goal here is to prevent possible attempts to change the contents of the memory pointed by ptr.
I can work-around this problem using #define ptr_t void* instead of typedef void* ptr_t.
But it doesn't feel like a proper solution in terms of coding correctness. Is there any alternative?
Thanks
Here's a C++ solution to turn a pointer-to-object into a pointer-to-const-object:
#include <type_traits>
template <typename T>
using more_const_ptr = typename std::enable_if<
std::is_pointer<T>::value,
typename std::add_pointer<
typename std::add_const<
typename std::remove_pointer<T>::type>::type>::type>::type;
Usage:
using p = int *; // or "typedef int * p;" in C++03
int a = 10;
more_const_ptr<p> q = &a;
// *q = 20; // Error, q is "const int *"
(In C++14 there are useful shortcuts that make this more readable:)
template <typename T>
using more_const_ptr = std::enable_if_t<
std::is_pointer<T>::value,
std::add_pointer_t<std::add_const_t<std::remove_pointer_t<T>>>>;
In line 1, as you say you have a pointer type and then make it const. This means you have a constant pointer to (non-constant) data. Declaring it as type const won't solve anything, because C specifies that such a declaration is equivalent to const type.
There is no work-around. Generally, it is a bad idea to hide a pointer underneath a typedef. This makes the code very hard to read, even if you have a coding standard for variable naming. Just look at the Windows API for a perfect example of how to turn the C language into something less readable.
So the quick & dirty solution is to keep digging your hole deeper by declaring a typedef const void* cptr_t;. Or indeed use a macro, it is an equally bad solution.
The good solution is to forget all about hiding pointers behind typedefs and other such attempts to change the well-known C or C++ language into some mysterious, personal macro language.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With