Tornar uma classe indefinida como amiga e defini-la mais tarde

Fazendo um amigo desconhecido

template<typename T>
class List
{
protected:

    class a {
        int x;
        int y;
    private:
        friend class b;  // <------------ Why this is not an error? 
    };

    template <typename U > class b {  //If that is not a error this should be an error
        int z;
        U y;
    };

    public:
        List() {
            a* ptr = (a *)new unsigned char[sizeof(a)];
        }
};

int main() {
    List<int>  mylist;
}

Por favor, acesse este link, tenho minhas perguntas como comentários no código. Estou tentando fazer de outra classe um amigo da minha classe. Mas essa classe não é conhecida na hora de fazer amizade. Qual é a regra C ++ que permite isso? Mais tarde, defini essa classe de forma que seja incompatível com a declaração de amigo. Por que isso não está gerando um erro. obrigado