Writing Merge Sort in C++
std::ceil(static_cast&lt;double&gt;(size) / 2 is a very long (and unclear) way to say size - size/2.
No naked loops please. Each loop represents an important algorithm, and deserves a name. For example,

while (array1 != array1end)
    new_array[na_pos++] = *array1++;


wants to be copy(new_array + na_pos, array1, array1_end);, and you may reuse it at least 2 more times (and don't make it void: it has something interesting to return).

Similarly, the merging loop represents a merge algorithm.
The block

if (*array1 &lt; *array2)
    new_array[na_pos++] = *array1++;
else if (*array2 &lt; *array1)
    new_array[na_pos++] = *array2++;
else if (*array1 == *array2) {
    new_array[na_pos++] = *array1++;
    new_array[na_pos++] = *array2++;
}


introduces a subtle problem. Here your algorithm may lose stability. If array1 has two elements comparing equal, say x1,x2, and array2 has an element x3 which also compares equal to them, the final arrangement will be x1, x3, x2, whereas the stable sort should result in x1, x2, x3.

The problem is easy to fix:

if (*array1 &lt;= *array2) {
    new_array[na_pos++] = *array1++;
} else {
    new_array[na_pos++] = *array2++;
}

I strongly recommend to put the loop termination conditions where they belong:

while ((array1 != array1end) &amp;&amp; (array2 != array2end))