replace typeid-based with template-based approach