Naja, unantastbar ist (fast) nix. Wenn du aber Otto-Normal-Programmierer verbieten willst da drauf zuzugreifen, aber gleichzeitig Zugriffe aus inline Funktionen brauchst, ist vielleicht wirklich das Beste wenn du die Daten als "private static" in einen eigene Klasse packst. Die Funktionen kannst du ja trotzdem als free functions implementieren (müssen dann halt alle friend sein). Oder, wenn dir der Aufwand zuviel ist (immer friend Tippen etc.), dann halt wirklich so wie du es ursprünglich geschrieben hast. Die Klasse für diese Daten packst du dann ein einen Detail namespace, und *futsch* sind sie "weg"
Je nachdem was du wirklich machst könnte es von der Geschwindigkeit her trotzdem vertretbar sein wenn du einfach ne Klasse machst die mehrfach instanzierbar ist, da alle wichtigen Funktionen (was eben schnell gehen muss) inline implementierst, und überall einen Pointer/eine Referenz auf die zu verwendende Instanz mitgibst. Dass der Compiler Member-Function-Calls nicht "inlinen" kann ist nämlich ein (unwahres) Gerücht, zumindest was MSVC angeht (ab Version 6 kann der das sicher). Das einzige was dann noch an Overhead bleibt ist der "this" Pointer, was aber nahezu vernachlässigbar ist. Das eine Register wird ihm schon nicht SO weh tun
Und je nachdem was du machst kann es durchaus Sinn machen diese Kontrollklasse mehrfach instanzierbar zu machen. Man denke an Multithreading. Nix ist lästiger als eine Library die wegen globalem State nicht thread-safe ist. Wenn es allerdings bloss um eine halbwegs überschaubare (Grösse, Komplexität) Applikation geht kann es leicht sein dass jeglicher Aufwand für super-schönes Design vollkommen verschwendet ist, weils eh nie jmd. brauchen wird.
Oft gilt aber "mutable (global) state" + multithreading = desaster.
Wenn du etwas genauer beschreiben kannst was diese Klasse/Funktionssammlung eigentlich tun soll könnte vielleicht jmd. mit persönlicher Erfahrung weiterhelfen.
Und: vergiss nicht das "static initialization order fiasco" - weiss nicht ob es dich betreffen kann, ist aber ein oft ignoriertes Problem bei Singletons (wie auch immer implementiert), das sich manchmal grausam rächt.
p.S.: das "pointer holen" beim Singleton Pattern kann, je nach Implementierung (z.B. thread-safe oder nicht), sehr teuer werden. Deswegen ziehe ich normalerweise vor den Zeiger (bzw. die Referenz) einfach überall mitzugeben wo man ihn braucht, dann muss man den nicht so oft "neu ermitteln".
p.p.S.: wenn du MSVC verwendest guck dir mal "#pragma inline_depth()" an - "#pragma inline_depth(255)" wirkt oft Wunder, vor allem bei sehr "schönem" Code (viele Indirections die kaum "echten" Code enthalten). (Default ist 8 und da kommt man schnell mal drüber.) Und ggf. noch "#pragma inline_recursion(on)". Und Link-Time-Code-Generation wurde ja schon erwähnt, wirkt manchmal auch Wunder (wenn auch nicht ganz SO oft). Und ggf. den Buffer-Security-Check abdrehen, checked iterator abdrehen etc. wenns auf Performance ankommt, und der Vergleich zeigt dass es deutlich was bringt.