'Making a namespace a friend of a class?

I'm trying to encapsulate the Allegro5 C++ library and I want to have a namespace of rendering functions. The problem is that in order to use the rendering functions I need to have access to the private ALLEGRO_BITMAP variable within Sprite. In theory I could just make all the functions friends of the sprites but that would be very poorly organized. Another Option would be to have a class with rendering functions and make the class a friend of the sprite. Is there a simpler way of achieving this that I am not thinking of?

#include <allegro.h>
#include "Sprite.h"

namespace Rendering
{
    

    //void RenderSprite(Sprite sprite)
    //{
    //  al_draw_bitmap(sprite.mpBitmap);
    //}
}
#pragma once

#include <allegro.h>


class Sprite
{
    
public:

    Sprite();
    Sprite(char* filepath);
    ~Sprite();

    Sprite clone();
    int getHeight();
    int getWidth();
    void loadBitmap(char* filePath);
private:

    ALLEGRO_BITMAP* mpBitmap;

    Sprite(const Sprite& sprite) = delete;

};

Update:

So I have seen a few comments asking why the member variable in sprite needs to be private. The purpose of this is to help maintain the concept of Encapsulation and hide the Allegro code from the end user of the library. The ultimate goal is for the end user to never need to use allegro code because the library will hide the implementation details of it.

As for why I cant make a getter for it. This would leave me with a "leaky abstraction" in the words of my professor taking away from the encapsulation.




Solution 1:[1]

In C++ you cannot have friend namespaces. What you can however have is friend classes, which may just happen to have a lot of static methods (you can practically use it as a namespace). For example:

//Sprite.h
#pragma once

#include <allegro.h>


class Sprite
{
    
public:

    Sprite();
    Sprite(char* filepath);
    ~Sprite();

    Sprite clone();
    int getHeight();
    int getWidth();
    void loadBitmap(char* filePath);
private:

    ALLEGRO_BITMAP* mpBitmap;

    Sprite(const Sprite& sprite) = delete;


    friend class Rendering;

};
//Rendering.h
#include <allegro.h>
#include "Sprite.h"
class Rendering
{
    

    static void RenderSprite(Sprite sprite)
    {
      al_draw_bitmap(sprite.mpBitmap);
    }
}

The other solution, as you said yourself, would be to befriend every individual function, which I think you should try to avoid.

NOTE: Also, I noticed you had a clone function, that returned a Sprite object. That's pointless, because you can just use the default copy ctor: Sprite(&Sprite s) = default;.

What you might have wanted to do, if you were using polymorphism (are you used to using Java?), is have a virtual clone() function that returns a Sprite*, so that you even if you had casted your sprite to a superclass, the correct clone method would be called, and you would actually get a copy of the Sprite.

But none of that interests you at this point. Just remove the clone function and use the copy ctor.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1