The Problem
The restrict keyword in C is missing in C++, so out of interest I was looking for a way to emulate the same feature in C++.
Specifically, I would like the following to be equivalent:
// C
void func(S *restrict a, S *restrict b)
// C++
void func(noalias<S, 1> a, noalias<S, 2> b)
where noalias<T, n>
- behaves just like
T*when accessed with->and* - can be constructed from an
T*(so that the function can be called asfunc(t1, t2), wheret1andt2are both of typeT*) - the index
nspecifies the "aliasing class" of the variable, so that variables of typenoalias<T, n>andnoalias<T, m>may be assumed never to alias for n != m.
An Attempt
Here is my deeply flawed solution:
template <typename T, int n>
class noalias
{
struct T2 : T {};
T *t;
public:
noalias(T *t_) : t(t_) {}
T2 *operator->() const {return static_cast<T2*>(t);} // <-- UB
};
When accessed with ->, it casts the internally-stored T* to a noalias<T, n>::T2* and returns that instead. Since this is a different type for each n, the strict aliasing rule ensures that they will never alias. Also, since T2 derives from T, the returned pointer behaves just like a T*. Great!
Even better, the code compiles and the assembly output confirms that it has the desired effect.
The problem is the static_cast. If t were really pointing to an object of type T2 then this would be fine. But t points to a T so this is UB. In practice, since T2 is a subclass which adds nothing extra to T it will probably have the same data layout, and so member accesses on the T2* will look for members at the same offsets as they occur in T and everything will be fine.
But having an n-dependent class is necessary for strict aliasing, and that this class derives from T is also necessary so that the pointer can be treated like a T*. So UB seems unavoidable.
Questions
Can this be done in c++14 without invoking UB - possibly using a completely different idea?
If not, then I have heard about a "dot operator" in c++1z; would it be possible with this?
If the above, will something similar to
noaliasbe appearing in the standard library?