Category Archives: Programming languages

Handling errors at compile time in C++

We had a discussion with colleagues on why in the following code we cannot simply use

static_assert(false)

but need to do a trick with ‘always_false’:

#include <type_traits>

template<typename>
struct always_false : std::false_type {};

template<typename Type>
constexpr int Get()
{
    if constexpr (std::is_same_v<Type, int>)
    {
        return 1;
    }
    else if constexpr (std::is_same_v<Type, bool>)
    {
        return 2;
    }
    else {
        static_assert(always_false<Type>::value);
    }
}
(more…)

Conversion of S75 charts to GeoJSON with GDAL org2org utility.

The original S57 map consists of the following layers:

ogrinfo E:\temp\ENC_ROOT\US4CA11M\US4CA11M.000
INFO: Open of `E:\temp\ENC_ROOT\US4CA11M\US4CA11M.000'
      using driver `S57' successful.
1: DSID (None)
2: Point (Point)
3: Line (Line String)
4: Area (Polygon)
5: Meta (None)

So I was able to convert each layer separately one by one without errors:

ogr2ogr -f GeoJSON US1HA02M-Area.json E:\temp\ENC_ROOT\US1HA02M\US1HA02M.000 Area -lco RFC7946=YES -skipfailures
ogr2ogr -f GeoJSON US1HA02M-Point.json E:\temp\ENC_ROOT\US1HA02M\US1HA02M.000 Point -lco RFC7946=YES -skipfailures
ogr2ogr -f GeoJSON US1HA02M-Line.json E:\temp\ENC_ROOT\US1HA02M\US1HA02M.000 Line -lco RFC7946=YES -skipfailures
ogr2ogr -f GeoJSON US1HA02M-DSID.json E:\temp\ENC_ROOT\US1HA02M\US1HA02M.000 DSID -lco RFC7946=YES -skipfailures
Warning 1: No SRS set on layer. Assuming it is long/lat on WGS84 ellipsoid
ogr2ogr -f GeoJSON US1HA02M-Meta.json E:\temp\ENC_ROOT\US1HA02M\US1HA02M.000 Meta -lco RFC7946=YES -skipfailures
Warning 1: No SRS set on layer. Assuming it is long/lat on WGS84 ellipsoid

(more…)

Setting up Vue.js development tools on Windows 10.

I installed Node.js and Vue.js cli with the following commands

npm install -g @vue/cli
npm install -g @vue/cli-init

and a sample application with

vue init webpack-simple my-vue-app
cd my-vue-app
npm install
npm run dev

(more…)

PHP script that saves client IP address to a file.

Below I wrote down a simple PHP script that saves client IP address to a file. If the IP address of your home machine periodically changes, you can store it on a web server once a minute by scheduling a task like this:

sudo crontab -u <user> -e
* * * * * wget -q -O /dev/null -o /dev/null "https://yourwebsite.com/ip.php?rig=rig1&password=XXXXX"

where ip.php is the following PHP script:
(more…)

How to run WIX bootstrapper application UI with elevated privileges?

WIX bootstrapper application (BA) can easily determine if it runs as admin with the following code:

using System;
using System.Diagnostics;
using System.Security.Principal;

static bool IsAdmin()
{
    WindowsIdentity id = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(id);
    return principal.IsInRole(WindowsBuiltInRole.Administrator);
}

and if it does not, run a new instance as admin and exit:

static void RunAsAdmin()
{
    ProcessStartInfo proc = new ProcessStartInfo
    {
        UseShellExecute = true,
        WorkingDirectory = Environment.CurrentDirectory,
        FileName = Process.GetCurrentProcess().MainModule.FileName,
        Verb = "runas"
    };

    Process.Start(proc);
}

(more…)

Exponential growth policy of std::vector

Once std::vector is filled (size() equals to capacity()), a subsequent push_back(…) results in an exponential expansion of the vector capacity. The following table shows that the expansion happens when the index reaches a power of two:

index: 0, capacity: 1, address: 0x1fa6c20
index: 1, capacity: 2, address: 0x1fa6c40
index: 2, capacity: 4, address: 0x1fa6c20
index: 4, capacity: 8, address: 0x1fa6c60
index: 8, capacity: 16, address: 0x1fa6c90
index: 16, capacity: 32, address: 0x1fa6ce0
index: 32, capacity: 64, address: 0x1fa6d70
index: 64, capacity: 128, address: 0x1fa6e80
index: 128, capacity: 256, address: 0x1fa7090
index: 256, capacity: 512, address: 0x1fa74a0
index: 512, capacity: 1024, address: 0x1fa7cb0
index: 1024, capacity: 2048, address: 0x1fa8cc0
index: 2048, capacity: 4096, address: 0x1faacd0
index: 4096, capacity: 8192, address: 0x1faece0
index: 8192, capacity: 16384, address: 0x1fb6cf0
index: 16384, capacity: 32768, address: 0x1fc6d00
index: 32768, capacity: 65536, address: 0x1fe6d10
index: 65536, capacity: 131072, address: 0x2026d20
index: 131072, capacity: 262144, address: 0x20a6d30
index: 262144, capacity: 524288, address: 0x21a6d40
index: 524288, capacity: 1048576, address: 0x23a6d50
index: 1048576, capacity: 2097152, address: 0x27a6d60
index: 2097152, capacity: 4194304, address: 0x2fa6d70
index: 4194304, capacity: 8388608, address: 0x7f8e9225f010
index: 8388608, capacity: 16777216, address: 0x7f8e8e25e010
index: 16777216, capacity: 33554432, address: 0x7f8e8625d010
index: 33554432, capacity: 67108864, address: 0x7f8e7625c010
index: 67108864, capacity: 134217728, address: 0x7f8e5625b010
index: 134217728, capacity: 268435456, address: 0x7f8e1625a010
index: 268435456, capacity: 536870912, address: 0x7f8d96259010
index: 536870912, capacity: 1073741824, address: 0x7f8c96258010

(more…)

How to erase an element with a reverse iterator from C++ container

The following C++ code demonstrates how to erase an element a reverse iterator points to:

#include <iostream>
#include <set>
#include <cassert>

int main()
{
    std::set<int> set;
 
    set.insert(15);
 
    std::cout << set.size() << " ";
 
    auto ri = set.rbegin();
 
    auto i1 = --ri.base();
 
    auto i2 = --set.end();
 
    assert(i1 == i2);
 
    set.erase(i1);
 
    std::cout << set.size() << std::endl;
}

The output is ‘1 0’. The key point here is that the reverse iterator is an adaptor for reverse-order traversal that can be created from forward iterator with std::make_reverse_iterator.

An example of how GCC thread sanitizer works.

The following simple code C++ example can be used for investigation of how GCC thread sanitizer works:

#include <mutex>
#include <atomic>
#include <iostream>
#include <thread>

std::mutex mutex;
int a = 3;
const size_t size = 1000 * 1000;
std::atomic<int> b(1);

void testA()
{
	for (size_t counter = 0; counter < size; counter++)
	{
		++b;
		std::unique_lock<std::mutex> lock(mutex);
		++a;
	}
}

void testB()
{
	for (size_t counter = 0; counter < size; counter++)
	{
		--b;
		std::unique_lock<std::mutex> lock(mutex);
		--a;
	}
}

int main()
{
	std::thread t1(testA);
	std::thread t2(testB);
	t1.join();
	t2.join();
}

(more…)

Multiple views with OsgQtQuick

I wrote a sample application using OsgQtQuick that shows the Earth in two views:

with the following QML, that I copied from OsgQtQuick samples:

(more…)

A sample C++ code demonstrating why int is not atomic

The code below demonstrates why it is not guaranteed that 4-byte value being written by another thread is read either as original or final, but it can be read “partially written”:

static constexpr int offset=2;
alignas(64) char vars[64+4-offset];
static volatile unsigned * const p = reinterpret_cast<unsigned *>(&vars[64-offset]);

unsigned getVar()
{
    return *p;
}

void loop()
{
    while(true)
    {
        *p = -1;
        *p = 0;
    }
}

#include <thread>
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <map>

int main()
{
    std::thread thread(loop);
    std::map<unsigned,int> xs;
    for(int i=0;i<10000000;++i)
    {
        const auto x=getVar();
        ++xs[x];
    }
    for(const auto& x : xs)
        std::cout << std::setfill('0') << std::setw(8) << std::hex << x.first << ": " << std::dec << x.second << " times\n";
    std::exit(0); // exit, killing the thread without abnormal termination via std::terminate
}

(more…)