Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 4250140
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 21, 20262026-05-21T04:29:21+00:00 2026-05-21T04:29:21+00:00

Are (seemingly) shady things ever acceptable for practical reasons? First, a bit of background

  • 0

Are (seemingly) shady things ever acceptable for practical reasons?

First, a bit of background on my code. I’m writing the graphics module of my 2D game. My module contains more than two classes, but I’ll only mention two in here: Font and GraphicsRenderer.

Font provides an interface through which to load (and release) files and nothing much more. In my Font header I don’t want any implementation details to leak, and that includes the data types of the third-party library I’m using. The way I prevent the third-party lib from being visible in the header is through an incomplete type (I understand this is standard practice):

class Font
{
  private:
    struct FontData;
    boost::shared_ptr<FontData> data_;
};

GraphicsRenderer is the (read: singleton) device that initializes and finalizes the third-party graphics library and also is used to render graphical objects (such as Fonts, Images, etc). The reason it’s a singleton is because, as I’ve said, the class initializes the third-party library automatically; it does this when the singleton object is created and exits the library when the singleton is destroyed.

Anyway, in order for GR to be able to render Font it must obviously have access to its FontData object. One option would be to have a public getter, but that would expose the implementation of Font (no other class other than Font and GR should care about FontData). Instead I considered it’s better to make GR a friend of Font.

Note: Until now I’ve done two things that some may consider shady (singleton and friend), but these are not the things I want to ask you about. Nevertheless, if you think my rationale for making GR a singleton and a friend of Font is wrong please do criticize me and maybe offer better solutions.

The shady thing. So GR has access to Font::data_ though friendship, but how does it know exactly what a FontData is (since it’s not defined in the header, it’s an incomplete type)? I’ll just show the code and the comment that includes the rationale…

// =============================================================================
//   graphics/font.cpp
// -----------------------------------------------------------------------------

struct Font::FontData
    : public sf::Font
{
    // Just a synonym of sf::Font
};

// A redefinition of FontData exists in GraphicsRenderer::printText(),
// which will have to be modified as well if this definition is modified.
// (The redefinition is called FontDataSurogate.)
// Why not have FontData defined only once in a separate header:
// If the definition of FontData changes, most likely printText() text will
// have to be altered also regardless. Considering that and also that FontData
// has (and should have) a very simple definition, a separate header was
// considered too much of an overhead and of little practical advantage.


// =============================================================================
//   graphics/graphics_renderer.cpp
// -----------------------------------------------------------------------------

void GraphicsRenderer::printText(const Font& fnt /* ... */)
{
    struct FontDataSurogate
        : public sf::Font {
    };

    FontDataSurogate* suro = (FontDataSurogate*)fnt.data_.get();
    sf::Font& font = (sf::Font)(*suro);

    // ...
}

So that’s the shady thing I’m trying to do. Basically what I want is a review of my rationale, so please tell me if you think I’ve done something horrendous or if not confirm my rationale so I can be a bit surer I’m doing the right thing. 🙂 (This is my biggest project yet and I’m only at the beginning so I’m kinda feeling things in the dark atm.)

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-21T04:29:22+00:00Added an answer on May 21, 2026 at 4:29 am

    In general, if something looks sketchy, I’ve found that it’s often worth going back a few times and trying to figure out exactly why that’s necessary. In most cases, some kind of fix pops up (maybe not as “nice”, but not relying on any kind of trick).

    Now, the first issue I see in your example is this bit of code:

    struct FontDataSurogate
        : public sf::Font {
    };
    

    occurs twice, in different files (neither being a header). That may come back and be a bother when you change one but not the other in the future, and making sure both are identical will very likely be a pain.

    To solve that, I would suggest putting the definition to FontDataSurogate and the appropriate includes (whatever library/header defines sf::Font) in a separate header. From the two files that need to use FontDataSurogate, include that definition header (not from any other code files or headers, just those two).

    If you have a main class declaration header for your library, place the forward declaration for the class there, and use pointers in your objects and parameters (regular pointers or shared pointers).

    You can then use friend or add a get method to retrieve the data, but by moving the class definition to its own header, you’ve created a single copy of that code and have a single object/file that’s interfacing with the other library.

    Edit:
    You commented on the question while I was writing this, so I’ll add on a reply to your comment.

    “Too much overhead” – more to document, one more thing to include, the complexity of the code grows, etc.

    Not so. You will have one copy of the code, compared to the two that must remain identical now. The code exists either way, so it needs documented, but your complexity and particularly maintenance is simplified. You do gain two #include statements, but is that such a high cost?

    “Little practical advantage” – printText() would have to be modified every time FontData is modified regardless of whether or not it’s defined in a separate header or not.

    The advantage is less duplicate code, making it easier to maintain for you (and others). Modifying the function when the input data changes is not surprising or unusual really. Moving it to another header doesn’t cost you anything but the mentioned includes.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I was writing a (seemingly) straight-forward SQL snippet that drops a column after it
I am feeling surprised by the difference between two seemingly identical scripts. first.ps1: A
I'm using Vim to write text that isn't code, just free form writing. To
Seemingly simple, but I cannot find anything relevant on the web. What is the
Seemingly a simple enough question, but I cannot work it out. I want to
I have a seemingly simple problem though i am unable to get my head
I was always wondering about this seemingly utopic world of open source. Assuming the
i recently stumbled upon a seemingly weird behavior that Google completely failed to explain.
Every time I try to do something seemingly-simple in CSS, it doesn't work. I
I'm stuck on a RegEx problem that's seemingly very simple and yet I can't

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.