The simple answer is: make typedef post open.
This will leak a minor implementation detail (actual internal type), but since it has been changed, you can redefine it at any time, and that should be fine.
A little less simple: make friends with a helper function by providing access to your inner type.
The problem with this second approach is that you not only provide access to typedef, but also to all the private parts of your class, and this may not be the best idea. In any case, since this is an internal auxiliary function, it is under your control, and everything should be fine. (Now that I think about it, you might want to declare a function in a named namespace so that the friend declaration succeeds)
Even less simple: create a separate typedef file inside the implementation file and make sure they are in sync.
You can guarantee that the types will be the same with a little metaprogramming, with the same_type<T,U> pattern that will provide true if the two types are the same and false otherwise. Static statement throws error if typedef changes in only one place
To return to the simple: enter typedef or use the type directly without static assert.
You call the function (it should not be a template, as in your code) and pass the link. If the typedef changes in the class, the call will fail and the compiler will tell you.
I would use the latter option, although it may look a little rude and less delicate than others, the fact is that this is only an implementation detail that is not used by others, you have full control over the code and it’s good, simpler.
EDIT after comment.
I started writing this as a comment, but it got too long, so I am adding it to the answer.
There is nothing wrong with this solution, except that you arbitrarily perform the generic function, and some error messages in the future may not be as simple as they may be with a non-piggy signature. Note that template will not expose a typedef (as the name of the question suggests), but rather will make the compiler infer the type at the call point.
If you change the typedef , instead of receiving an error message indicating that the helperFn arguments cannot be matched with an existing function, the type will be inferred and the function will match, but you will get an error deeper in helperFn if you use a property of the type that no longer present. Or, even worse, you cannot even get an error message if it is semantics of a changed type.
Note that typedef has the value std::list<X> , and in the function that you execute with this simple correct loop:
for (typename T::iterator it=x.begin(), end=x.end(); it != end; ) { if ( condition(*it) ) it = x.erase(it); else ++it; }
Can you catch an effect that changes the typedef type to std::vector<X> ? The compiler cannot even if the code is now incorrect. Regardless of whether the for loop entry is similar, is it a good idea or why is it not just using the delete-delete idiom - these are different problems (in fact, the previous cycle is probably better than delete-delete for a list), the specific situation is that the semantics have changed, and since the type is syntactically compatible with the previous one, the compiler will not notice that the code is incorrect, it will not point you to this function, and most likely you will not revise / rewrite it.