November 2015

13:33
Sat
21
Nov 2015

type_safe_ptr - Idea for Type-Safe void* Pointer

I was thinking recently about passing raw data pointers (like void* or char*), which we have to do sometimes in C++. Is there any way to check if the type that we cast it to is the same as the type of last assigned value? I came up with an idea of implementing a "smart pointer" class using RTTI (specifically typeof operator) to store type information next to the actual pointer. Example usage:

int i = 123;
type_safe_ptr ptr{&i};
int j = *ptr.get_typed<int>(); // OK
float f = *ptr.get_typed<float>(); // Error

Initially I wanted to store pointer to const type_info struct returned by typeid operator, and it seems to work in Visual Studio 2015, but language standard defines the object returned by typeid as temporary, so it is not formally correct. Finally I decided to store typeid(T).hash_code(). You can find my implementation of classes type_safe_ptr and type_safe_const_ptr in file: type_safe_ptr.hpp. Here is example tesing program:

#include <cstdio>
#include "type_safe_ptr.hpp"

int main()
{
    type_safe_ptr ptr1;
    // ptr1 is null.
    assert(!ptr1);
    assert(ptr1.get() == nullptr);

    int i = 123;
    type_safe_ptr ptr2{&i};
    // ptr2 is pointer to int.
    assert(*ptr2.get_typed<int>() == 123);
    // It would activate assert inside type_safe_ptr.get_typed, because ptr2 is int not float.
    //assert(*ptr2.get_typed<float>() == 123.f);

    struct STest { int i; } obj;
    // itr2 is now pointer to STest.
    ptr2 = &obj;
    ptr2.get_typed<STest>()->i = 124;
    assert(obj.i == 124);
    // It would activate assert inside type_safe_ptr.get_typed, because ptr2 is now STest not int.
    //assert(*ptr2.get_typed<int>() == 123);
    
    type_safe_const_ptr cptr = type_safe_const_ptr(ptr2);
    // cptr is pointer to const STest.
    assert(cptr.get_typed<STest>()->i == 124);

    const int* constIntPtr = &i;
    cptr.reset(constIntPtr);
    // cptr is now pointer to const int.
    assert(*cptr.get_typed<int>() == 123);
}

Some issues and open question regarding my solution are:

Final question is, whether this whole idea of "type-checking void* smart pointer" makes any sense? I am not sure about that, but anyway it was a funny experiment :)

Comments (1) | Tags: c++ visual studio | Author: Adam Sawicki | Share

18:59
Wed
11
Nov 2015

The Virtual Reality of Code

In my opinion, coding is a virtual reality with its own set of rules unlike in the physical world. In physical world, each thing has its specific location at the moment, things don't appear or disappear instantly, we have laws of energy and mass conservation. Inside a computer, we have data in memory (which is actually linear - 1D) and processors, processes and threads executing instructions of a program over time.

I have been trying for years to imagine some nice way editing or at least visualizing code, which would be more convenient (and look more attractive) than the text representation we all use. I am unsuccessful, because even if we render some nice looking depiction of a function code, its instructions, conditions and loops, drawing all the connections with variables and functions that this code uses would clutter the image too much. It's just like this virtual world doesn't fit into a 2D or 3D world.



Movie depiction of computer programs is often visually attractive, but far from being practical. This one comes from "Hackers" movie.

Of course there are ways of explaining a computer program on a diagram, e.g. entity diagrams or UML notation. I think that electrical diagrams are something in between. Electrical devices end up as physical things, but on a diagram, the shape, size and position of specific elements doesn't match how they will be arranged on a PCB. Logical representation and electrical connections between them is the only thing that matters.

Today it occured to me that this virtual reality of code also has "dimensions", in its own sense. It's evident when learning programming.

1. First, one has to understand control flow - that the processor executes subsequent instructions of the program over time and that there can be jumps caused by conditions, loops, function calls and returns. It's called dynamic aspect of the code. It can be depicted e.g. by UML sequence diagram or activity diagram.

I still remember my colleague at university who couldn't understand this. What's obvious to every programmer, was a great mystery to him as first year's computer science student. He thought that when there is a function above main(), instructions of that function are executed first and then instructions of the main function. He just couldn't imagine the concept of calling one function from the other and returning from it.

2. Then, there is so called static aspect - data structures and objects that are in memory at given moment in time. This involves understanding that objects can be created in one place and destroyed in another place and at later time, that there may be a collection of multiple objects (arrays, lists, trees, graphs and other data structures), objects may be connected to one another (the concept of pointers or references). Various relationships are possible, like one-to-one and one-to-many. In object-oriented methodologies, there is another layer of depth here, as there are classes and interfaces (with inheritance, composition etc.) and there are actual objects in memory that are instances of these classes. It can be depicted for example by entity diagram or UML class diagram.

3. Finally, one has to learn about version control systems that store history of the code. This adds another dimension to all the above, as over successive commits, developers make changes to the code - its structure and the way it works, including format of data structures it uses. Branches and merges add even more complexity to it. GUI apps for version control systems offer some way of visualizing this, whether it's showing a timeline with commits ("History") or showing who and when commited each line of a file ("Blame").

There is even more to it. Source is organized into files and directories, which may be more or less related to the structure of contained code. Multithreading (and coprocessing e.g. with GPU, SIMD, and all kinds of parallel programming) complicates imagining (and especially debugging!) control flow of the program. Program binaries and data may be distributed into multiple programs and machines that have to communicate.

It fascinates me how software is so multidimensional in its own way, while so flat at the same time (after all, computer memory is linear). I believe that becoming a programmer is all about learning how to imagine, navigate and create stuff in this virtual reality.

Comments (3) | Tags: philosophy software engineering | Author: Adam Sawicki | Share

STAT NO AD [Stat] [Admin] [STAT NO AD] [pub] [Mirror] Copyright © 2004-2017 Adam Sawicki
Copyright © 2004-2017 Adam Sawicki