I am trying to turn a function, createArray, into a constexpr function.
This function creates an array from a contiguous section in memory marked by two arbitrarily named variables _start_array and _stop_array. I am able to iterate between the two and when the program is ran it prints
foo
bar
baz
This is the code so far:
#include <iostream>
#include <string>
#include <array>
struct element {
std::string_view value;
};
__attribute__( (used, section("array$a" )) ) unsigned int _start_array = 0xdeadbeef;
__attribute__( (used, section("array$b" )) ) element _element1_array = { .value = "foo" };
__attribute__( (used, section("array$b" )) ) element _element2_array = { .value = "bar" };
__attribute__( (used, section("array$b" )) ) element _element3_array = { .value = "baz" };
__attribute__( (used, section("array$c" )) ) unsigned int _stop_array = 0xdeadc0de;
std::array< element, 3 > createArray () { // TODO: constexpr
std::array< element, 3 > array;
int i = 0;
for ( element* it = reinterpret_cast< element* >( &_start_array + sizeof( int ) ); it < reinterpret_cast<element*>(&_stop_array); it++ ) {
array[ i++ ] = *it;
}
return array;
}
int main ( int argc, char* argv[] ) {
for ( auto i : createArray() ) {
std::cout << i.value << std::endl;
}
}
I am using MinGW on Windows.
During constant expression evaluation, the C++ object model is treated as reality, not a fiction created by a piece of paper. This means that anything which would be undefined behavior at runtime becomes ill-formed during constant evaluation.
As such, pointers in constant evaluation are not merely numbers. They are pointers to a specific object with full and complete knowledge of what that means. So converting a pointer value to an integer makes no sense.
And even if it did, what are you going to do with it? The address has no relation to the address of any other object. The address cannot be manipulated and then converted to a pointer to some other object, because that's not how things work at compile-time. Again, the object model is taken seriously at compile-time. If you get a pointer from something, the system needs to be able to verify that the "something" points to a real object of that type (or a type appropriate to the pointer type). This requires a compile-time pointer to be more than just an address.
Put simply, you cannot "treat the memory between _start and _stop as an array" at compile-time, because it isn't an array. You cannot just pretend things are a certain way at compile-time. To be fair, you can't do that at runtime either with well-defined behavior; it's just that the compiler won't stop you.
No, there is no standard way to reinterpret pointers in constexpr contexts.
Furthermore, accessing objects through reinterpreted pointers is well defined only in a few specific cases. Arbitrary T* isn't necessarily such case.
Iterate over a section in memory between two variables
There's no standard way to do this in general. There's generally not even a guarantee that such memory is allocated for the process.
If the variables in question are members of a standard layout class, then this may be achievable, but I can't think of a constexpr way.
Related
I am learning C++ using C++ Primer 5th edition. In particular, i read about void*. There it is written that:
We cannot use a void* to operate on the object it addresses—we don’t know that object’s type, and the type determines what operations we can perform on that object.
void*: Pointer type that can point to any nonconst type. Such pointers may not
be dereferenced.
My question is that if we're not allowed to use a void* to operate on the object it addressess then why do we need a void*. Also, i am not sure if the above quoted statement from C++ Primer is technically correct because i am not able to understand what it is conveying. Maybe some examples can help me understand what the author meant when he said that "we cannot use a void* to operate on the object it addresses". So can someone please provide some example to clarify what the author meant and whether he is correct or incorrect in saying the above statement.
My question is that if we're not allowed to use a void* to operate on the object it addressess then why do we need a void*
It's indeed quite rare to need void* in C++. It's more common in C.
But where it's useful is type-erasure. For example, try to store an object of any type in a variable, determining the type at runtime. You'll find that hiding the type becomes essential to achieve that task.
What you may be missing is that it is possible to convert the void* back to the typed pointer afterwards (or in special cases, you can reinterpret as another pointer type), which allows you to operate on the object.
Maybe some examples can help me understand what the author meant when he said that "we cannot use a void* to operate on the object it addresses"
Example:
int i;
int* int_ptr = &i;
void* void_ptr = &i;
*int_ptr = 42; // OK
*void_ptr = 42; // ill-formed
As the example demonstrates, we cannot modify the pointed int object through the pointer to void.
so since a void* has no size(as written in the answer by PMF)
Their answer is misleading or you've misunderstood. The pointer has a size. But since there is no information about the type of the pointed object, the size of the pointed object is unknown. In a way, that's part of why it can point to an object of any size.
so how can a int* on the right hand side be implicitly converted to a void*
All pointers to objects can implicitly be converted to void* because the language rules say so.
Yes, the author is right.
A pointer of type void* cannot be dereferenced, because it has no size1. The compiler would not know how much data he needs to get from that address if you try to access it:
void* myData = std::malloc(1000); // Allocate some memory (note that the return type of malloc() is void*)
int value = *myData; // Error, can't dereference
int field = myData->myField; // Error, a void pointer obviously has no fields
The first example fails because the compiler doesn't know how much data to get. We need to tell it the size of the data to get:
int value = *(int*)myData; // Now fine, we have casted the pointer to int*
int value = *(char*)myData; // Fine too, but NOT the same as above!
or, to be more in the C++-world:
int value = *static_cast<int*>(myData);
int value = *static_cast<char*>(myData);
The two examples return a different result, because the first gets an integer (32 bit on most systems) from the target address, while the second only gets a single byte and then moves that to a larger variable.
The reason why the use of void* is sometimes still useful is when the type of data doesn't matter much, like when just copying stuff around. Methods such as memset or memcpy take void* parameters, since they don't care about the actual structure of the data (but they need to be given the size explicitly). When working in C++ (as opposed to C) you'll not use these very often, though.
1 "No size" applies to the size of the destination object, not the size of the variable containing the pointer. sizeof(void*) is perfectly valid and returns, the size of a pointer variable. This is always equal to any other pointer size, so sizeof(void*)==sizeof(int*)==sizeof(MyClass*) is always true (for 99% of today's compilers at least). The type of the pointer however defines the size of the element it points to. And that is required for the compiler so he knows how much data he needs to get, or, when used with + or -, how much to add or subtract to get the address of the next or previous elements.
void * is basically a catch-all type. Any pointer type can be implicitly cast to void * without getting any errors. As such, it is mostly used in low level data manipulations, where all that matters is the data that some memory block contains, rather than what the data represents. On the flip side, when you have a void * pointer, it is impossible to determine directly which type it was originally. That's why you can't operate on the object it addresses.
if we try something like
typedef struct foo {
int key;
int value;
} t_foo;
void try_fill_with_zero(void *destination) {
destination->key = 0;
destination->value = 0;
}
int main() {
t_foo *foo_instance = malloc(sizeof(t_foo));
try_fill_with_zero(foo_instance, sizeof(t_foo));
}
we will get a compilation error because it is impossible to determine what type void *destination was, as soon as the address gets into try_fill_with_zero. That's an example of being unable to "use a void* to operate on the object it addresses"
Typically you will see something like this:
typedef struct foo {
int key;
int value;
} t_foo;
void init_with_zero(void *destination, size_t bytes) {
unsigned char *to_fill = (unsigned char *)destination;
for (int i = 0; i < bytes; i++) {
to_fill[i] = 0;
}
}
int main() {
t_foo *foo_instance = malloc(sizeof(t_foo));
int test_int;
init_with_zero(foo_instance, sizeof(t_foo));
init_with_zero(&test_int, sizeof(int));
}
Here we can operate on the memory that we pass to init_with_zero represented as bytes.
You can think of void * as representing missing knowledge about the associated type of the data at this address. You may still cast it to something else and then dereference it, if you know what is behind it. Example:
int n = 5;
void * p = (void *) &n;
At this point, p we have lost the type information for p and thus, the compiler does not know what to do with it. But if you know this p is an address to an integer, then you can use that information:
int * q = (int *) p;
int m = *q;
And m will be equal to n.
void is not a type like any other. There is no object of type void. Hence, there exists no way of operating on such pointers.
This is one of my favourite kind of questions because at first I was also so confused about void pointers.
Like the rest of the Answers above void * refers to a generic type of data.
Being a void pointer you must understand that it only holds the address of some kind of data or object.
No other information about the object itself, at first you are asking yourself why do you even need this if it's only able to hold an address. That's because you can still cast your pointer to a more specific kind of data, and that's the real power.
Making generic functions that works with all kind of data.
And to be more clear let's say you want to implement generic sorting algorithm.
The sorting algorithm has basically 2 steps:
The algorithm itself.
The comparation between the objects.
Here we will also talk about pointer functions.
Let's take for example qsort built in function
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))
We see that it takes the next parameters:
base − This is the pointer to the first element of the array to be sorted.
nitems − This is the number of elements in the array pointed by base.
size − This is the size in bytes of each element in the array.
compar − This is the function that compares two elements.
And based on the article that I referenced above we can do something like this:
int values[] = { 88, 56, 100, 2, 25 };
int cmpfunc (const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
int main () {
int n;
printf("Before sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
qsort(values, 5, sizeof(int), cmpfunc);
printf("\nAfter sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
return(0);
}
Where you can define your own custom compare function that can match any kind of data, there can be even a more complex data structure like a class instance of some kind of object you just define. Let's say a Person class, that has a field age and you want to sort all Persons by age.
And that's one example where you can use void * , you can abstract this and create other use cases based on this example.
It is true that is a C example, but I think, being something that appeared in C can make more sense of the real usage of void *. If you can understand what you can do with void * you are good to go.
For C++ you can also check templates, templates can let you achieve a generic type for your functions / objects.
I've taken over some code, and came across a weird reallocation of an array. This is a function from within an Array class (used by the JsonValue)
void reserve( uint32_t newCapacity ) {
if ( newCapacity > length + additionalCapacity ) {
newCapacity = std::min( newCapacity, length + std::numeric_limits<decltype( additionalCapacity )>::max() );
JsonValue *newPtr = new JsonValue[newCapacity];
if ( length > 0 ) {
memcpy( newPtr, values, length * sizeof( JsonValue ) );
memset( values, 0, length * sizeof( JsonValue ) );
}
delete[] values;
values = newPtr;
additionalCapacity = uint16_t( newCapacity - length );
}
}
I get the point of this; it is just allocating a new array, and doing a copy of the memory contents from the old array into the new array, then zero-ing out the old array's contents. I also know this was done in order to prevent calling destructors, and moves.
The JsonValue is a class with functions, and some data which is stored in a union (string, array, number, etc.).
My concern is whether this is actually defined behaviour or not. I know it works, and has not had a problem since we began using it a few months ago; but if its undefined then it doesn't mean it is going to keep working.
EDIT:
JsonValue looks something like this:
struct JsonValue {
// …
~JsonValue() {
switch ( details.type ) {
case Type::Array:
case Type::Object:
array.destroy();
break;
case Type::String:
delete[] string.buffer;
break;
default: break;
}
}
private:
struct Details {
Key key = Key::Unknown;
Type type = Type::Null; // (0)
};
union {
Array array;
String string;
EmbedString embedString;
Number number;
Details details;
};
};
Where Array is a wrapper around an array of JsonValues, String is a char*, EmbedString is char[14], Number is a union of int, unsigned int, and double, Details contains the type of value it holds. All values have 16-bits of unused data at the beginning, which is used for Details. Example:
struct EmbedString {
uint16_t : 16;
char buffer[14] = { 0 };
};
Whether this code has well-defined behavior basically depends on two things: 1) is JsonValue trivially-copyable and, 2) if so, are a bunch of all-zero Bytes a valid object representation for a JsonValue.
If JsonValue is trivially-copyable, then the memcpy from one array of JsonValues to another will indeed be equivalent to copying all the elements over [basic.types]/3. If all-zeroes is a valid object representation for a JsonValue, then the memset should be ok (I believe this actually falls into a bit of a grey-area with the current wording of the standard, but I believe at least the intention would be that this is fine).
I'm not sure why you'd need to "prevent calling destructors and moves", but overwriting objects with zeroes does not prevent destructors from running. delete[] values will call the destructurs of the array members. And moving the elements of an array of trivially-copyable type should compile down to just copying over the bytes anyways.
Furthermore, I would suggest to get rid of these String and EmbedString classes and simply use std::string. At least, it would seem to me that the sole purpose of EmbedString is to manually perform small string optimization. Any std::string implementation worth its salt is already going to do exactly that under the hood. Note that std::string is not guaranteed (and will often not be) trivially-copyable. Thus, you cannot simply replace String and EmbedString with std::string while keeping the rest of this current implementation.
If you can use C++17, I would suggest to simply use std::variant instead of or at least inside this custom JsonValue implementation as that seems to be exactly what it's trying to do. If you need some common information stored in front of whatever the variant value may be, just have a suitable member holding that information in front of the member that holds the variant value rather than relying on every member of the union starting with the same couple of members (which would only be well-defined if all union members are standard-layout types that keep this information in their common initial sequence [class.mem]/23).
The sole purpose of Array would seem to be to serve as a vector that zeroes memory before deallocating it for security reasons. If this is the case, I would suggest to just use an std::vector with an allocator that zeros memory before deallocating instead. For example:
template <typename T>
struct ZeroingAllocator
{
using value_type = T;
T* allocate(std::size_t N)
{
return reinterpret_cast<T*>(new unsigned char[N * sizeof(T)]);
}
void deallocate(T* buffer, std::size_t N) noexcept
{
auto ptr = reinterpret_cast<volatile unsigned char*>(buffer);
std::fill(ptr, ptr + N, 0);
delete[] reinterpret_cast<unsigned char*>(buffer);
}
};
template <typename A, typename B>
bool operator ==(const ZeroingAllocator<A>&, const ZeroingAllocator<B>&) noexcept { return true; }
template <typename A, typename B>
bool operator !=(const ZeroingAllocator<A>&, const ZeroingAllocator<B>&) noexcept { return false; }
and then
using Array = std::vector<JsonValue, ZeroingAllocator<JsonValue>>;
Note: I fill the memory via volatile unsigned char* to prevent the compiler from optimizing away the zeroing. If you need to support overaligned types, you can replace the new[] and delete[] with direct calls to ::operator new and ::operator delete (doing this will prevent the compiler from optimizing away allocations). Pre C++17, you will have to allocate a sufficiently large buffer and then manually align the pointer, e.g., using std::align…
Consider the following type:
struct S
{
char v;
};
Given an array of const S, is it possible to, in a standard conformant way, reinterpret it as an array of const char whose elements correspond to the value of the member v for each of the original array's elements, and vice-versa? For example:
const S a1[] = { {'a'}, {'4'}, {'2'}, {'\0'} };
const char* a2 = reinterpret_cast< const char* >(a1);
for (int i = 0; i < 4; ++i)
std::cout << std::boolalpha << (a1[i].v == a2[i]) << ' ';
Is the code above portable and would it print true true true true? If not, is there any other way of achieving this?
Obviously, it is possible to create a new array and initialize it with the member v of each element of the original array, but the whole idea is to avoid creating a new array.
Trivially, no - the struct may have padding. And that flat out breaks any reinterpretation as an array.
Formally the struct may have padding so that its size is greater than 1.
I.e., formally you can't reinterpret_cast and have fully portable code, except for ¹an array of only one item.
But for the in-practice, some years ago someone asked if there was now any compiler that by default would give sizeof(T) > 1 for struct T{ char x; };. I have yet to see any example. So in practice one can just static_assert that the size is 1, and not worry at all that this static_assert will fail on some system.
I.e.,
S const a1[] = { {'a'}, {'4'}, {'2'}, {'\0'} };
static_assert( sizeof( S ) == 1, "!" );
char const* const a2 = reinterpret_cast<char const*>( a1 );
for( int i = 0; i < 4; ++i )
{
assert( a1[i].v == a2[i] );
}
Since it's possible to interpret the C++14 and later standards in a way where the indexing has Undefined Behavior, based on a peculiar interpretation of "array" as referring to some original array, one might instead write this code in a more awkward and verbose but guaranteed valid way:
// I do not recommend this, but it's one way to avoid problems with some compiler that's
// based on an unreasonable, impractical interpretation of the C++14 standard.
#include <assert.h>
#include <new>
auto main() -> int
{
struct S
{
char v;
};
int const compiler_specific_overhead = 0; // Redefine per compiler.
// With value 0 for the overhead the internal workings here, what happens
// in the machine code, is the same as /without/ this verbose work-around
// for one impractical interpretation of the standard.
int const n = 4;
static_assert( sizeof( S ) == 1, "!" );
char storage[n + compiler_specific_overhead];
S* const a1 = ::new( storage ) S[n];
assert( (void*)a1 == storage + compiler_specific_overhead );
for( int i = 0; i < n; ++i ) { a1[i].v = "a42"[i]; } // Whatever
// Here a2 points to items of the original `char` array, hence no indexing
// UB even with impractical interpretation of the C++14 standard.
// Note that the indexing-UB-free code from this point, is exactly the same
// source code as the first code example that some claim has indexing UB.
char const* const a2 = reinterpret_cast<char const*>( a1 );
for( int i = 0; i < n; ++i )
{
assert( a1[i].v == a2[i] );
}
}
Notes:
¹ The standard guarantees that there's no padding at the start of the struct.
The pointer arithmetic in a2[i] is undefined, see C++14 5.7 [expr.add] p7:
For addition or subtraction, if the expressions P or Q have type "pointer to cv T", where T and the array element type are not similar (4.5), the behavior is undefined. [ Note: In particular, a pointer to a base class cannot be used for pointer arithmetic when the array contains objects of a derived class type. — end note ]
Because of this rule, even if there is no padding and the sizes match, type-based alias analysis allows the compiler to assume that a1[i] and a2[i] do not overlap (because the pointer arithmetic is only valid if a2 really is an array of char not just something with the same size and alignment, and if it's really an array of char it must be a separate object from an array of S).
I think I'd be inclined to use a compile-time transformation if the source data is constant:
#include <iostream>
#include <array>
struct S
{
char v;
};
namespace detail {
template<std::size_t...Is>
constexpr auto to_cstring(const S* p, std::index_sequence<Is...>)
{
return std::array<char, sizeof...(Is)> {
p[Is].v...
};
}
}
template<std::size_t N>
constexpr auto to_cstring(const S (&arr)[N])
{
return detail::to_cstring(arr, std::make_index_sequence<N>());
}
int main()
{
const /*expr if you wish*/ S a1[] = { {'a'}, {'4'}, {'2'}, {'\0'} };
const /*expr if you wish*/ auto a2 = to_cstring(a1);
for (int i = 0; i < 4; ++i)
std::cout << std::boolalpha << (a1[i].v == a2[i]) << ' ';
}
output:
true true true true
even when the data is not a constexpr, gcc and clang are pretty good at constant folding complex sequences like this.
Pointers can be declared like this:
int
a = 1,
*b = &a, // 1st order pointer
**c = &b, // 2nd order pointer
***d = &c, // 3rd order pointer
****e = &d, // 4th order pointer
*****f = &e, // 5th order pointer
*** n-stars *** f; // n-th order pointer
Here, we need to know at compile-time the order of the pointer when we are declaring it.
Is it possible at all to declare a pointer, whose order is only known at run time? Linked to this question is whether is it possible to query at run-time the order of an arbitrary pointer?
int order = GET_ORDER_OF_PTR(f) // returns 5
int /* insert some syntax here to make ptr a pointer of order (order + 1) */ ptr = &f;
Note:
I already know this (generally) might not be a good idea. Still want to know if it's doable :)
In runtime you cannot - because C++ is statically typed. During compilation it is possible with templates, e.g.
template<typename T, int order> struct P
{
typedef typename P<T, order-1>::pointer* pointer;
};
template<typename T> struct P<T, 0>
{
typedef T pointer;
};
Then P<int, 3>::pointer is equivalent to int***.
You can't. C++ is statically typed, so the order of a pointer (which is part of its type) must be known at compile time.
Not in C or C++ because they're statically typed languages (i.e. the type of the values you store in a variable are known at compile time and fixed).
You can emulate this kind of possibility by defining a C++ class
template<typename T>
struct NPtr {
int order;
void *p; // order 0 -> T*, otherwise NPtr<T>*
NPtr(NPtr *ptr) : islast(ptr->order+1), p(ptr) {}
NPtr(T *final) : islast(0), ptr(final) {}
NPtr<T>& nptr() {
assert(order > 0);
return *(NPtr<T>*)p;
}
T& final() {
assert(order == 0);
return *(T*)p;
}
};
A TPtr<int> instance can either be a pointer to an integer (when order=0) or a pointer to another TPtr<int> instance.
The semantic equivalent of what you want is a linked list, with a number of node determined at runtime:
#include <iostream>
union kind_of_pointer
{
int data;
kind_of_pointer *next;
kind_of_pointer(int val) : data(val) {}
kind_of_pointer(kind_of_pointer* ptr) : next(ptr) {}
operator int()
{
return data;
}
kind_of_pointer& operator *()
{
return *next;
}
};
int main(void)
{
kind_of_pointer dyn_ptr{new kind_of_pointer{new kind_of_pointer{new kind_of_pointer{42}}}};
int*** static_ptr = new int**{new int *{new int{42}}};
std::cout << ***dyn_ptr << std::endl;
std::cout << ***static_ptr << std::endl;
}
I find this funny, interesting and horrible :)
You can do this:
int *f = nullptr;
decltype(f) *newptr = 0;
As for the
whether is it possible to query at run-time the order of an arbitrary
pointer?
part: no, you most definitely can not, unless you write your own wrapper-class that stores the order of the pointer. Pointer is, basically, a number: the address in memory.
This gives you at least one problem: you can't follow the pointer "all the way through" (which you would have to do to check if the thing your pointer is pointing at is itself a pointer) without potentially causing a segfault or reading "not your application's memory" (which is often prohibited by OS and will cause your application to be aborted; not sure about weather you can prevent this or not).
For example, NULL (or 0) can be cast to any pointer type, so is itself a pointer. But does it point to another pointer? Let's find out... BAM! SEGFAULT.
Oh, wait, there's another problem: you can cast (with c-style cast or with reinterpret_cast) pointer of any type to pointer of any other type. So, say, a might be pointing to a pointer, but was cast to a different type. Or a might have a type of "pointing to a pointer", but actually isn't pointing to one.
P.S. Sorry for using the verb "point" so freely.
... we need to know at compile-time the order of the pointer when we are declaring it.
Yes it is possible at compile time to determine the order of the pointer type being declared; based on the type (possibly via typedef) or the variable, if C++11 can be used (via decltype()).
#include <iostream>
using namespace std;
template <typename P>
struct ptr_order
{
static const int order = 0;
};
template <typename P>
struct ptr_order<P*>
{
static const int order = ptr_order<P>::order + 1;
};
int main()
{
typedef int*** pointer;
cout << ptr_order<pointer>::order << endl; // outputs 3
// could also use decltype if available...
// int*** p;
// ptr_order<decltype(p)>::order is also 3
}
The runtime calculation of the order of the pointer is not possible, since C++ is statically typed.
what would be the result if I wrote this
int array1[2];
cout << array1[0] ;
and how can I do this pseudocode :
if array1[0] doesn't have a value then assign its value to 1
I'm using C++ on DevCPP
The elements of array are uninitialized, and it is undefined behaviour to read them before writing to them. Your program is ill-formed. There is no way to "check" for this; it is your responsibility to write a correct program.
The initial value of unassigned array values is undefined (unless the array element type is a class/struct, in which case the default constructor will be called for each array element). In your first example, the behavior is undefined since you have not initialized the array element before using it.
If you want to retain an "unassigned" status then you need to use a class that encapsulates this, for example using the nullable pattern for value types.
Consider using Boost.Optional: you'd declare the array as boost::optional<int> array1[2]; and then you can test if (array1[0]) to see if that particular element has a value.
There is one point that the answers I'm seeing thus far seem to have missed. It depends on where your array is defined.
If the array is local to a function, like:
int f() {
int array1[2];
cout << array1[0] ;
}
...then the other answers are correct: the content of array1 contains unspecified values, and your attempt to read the value and send it to cout gives undefined behavior.
On the other hand, you may have defined array1 as a global variable:
int array1[2];
int f() {
cout << array1[0];
}
In this case, the content of array1 is required to be initialized to 0 for any arithmetic type (or NULL for an array of pointers). In a case like this, writing out the value in array1[0] is perfectly fine and gives defined results -- it must be 0. In this case, there is no any way to tell whether an element of an array containing the value 0 has that value because it was automatically initialized to 0, or was assigned that value later.
If you really need to know whether a value has been written to a variable, it's possible to write a class that will do that:
template <class T>
class value {
T val;
bool assigned;
public:
value(T const init=T()) : assigned(false), val(init) {}
value &operator=(T const &t) {
assigned = true;
val = t;
}
operator T() { return val; }
bool was_assigned() { return assigned; }
};
// ...
value<int> array2[2];
if (!array2[0].was_assigned())
array2[0] = 1;
It's usually easier and more efficient to just define the type to always start out initialized to a known value, so you never really care about whether it's been assigned to or not though. In short, although this supports what you've asked for, my immediate reaction is that there's probably a better/cleaner way to accomplish your ultimate goal. Before you even consider using something like this, I'd strongly recommend stepping back from what you're doing, and trying to figure out if there's a better way to do it. My guess is that there is/will be (and if you can't find it, you might want to ask another question, telling us about why you're trying to do this, to see if somebody can see a more direct way to accomplish your goal).
As far I remember that depend on the OS
As other users said, you need to initialize a then use a for loop to test each value one by one and modify them, if they fulfill a condition, I leave you a C snippet:
/* Variable declaration and initialization to 0s (You can use another value as default )*/
int a[ 5 ] = { 0 };
/* If the array[ i ] has 0 as value */
for( i = 0; i < 5; i++){
if ( a[ i ] == 0 ){
a[ i ] = 1;
}
}
If you don't initialise the element yourself, the element will obtain the value from the memory location it is stored on now (and will most probably convert it to its data type). Consider this program :
#include <iostream>
using namespace std;
int foo(int A[])
{
cout << A[0] << A[1];
}
int main()
{
int array[2];
foo(array);
}
This will give the output 00.
But now consider this code :
int main()
{
int array[2];
cout << array[0] << array[1];
}
It will give some random integer output. This is so because the uninitialised array picks up the value stored on the memory location it now occupies. You can check its memory adress by &array[0] and print it in different data types for some thought provoking questions.
eg: cout << &array[0] << char(array[0]) << bool(array[0]) etc.