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)
, wheret1
andt2
are both of typeT*
) - the index
n
specifies 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
noalias
be appearing in the standard library?