'Helper' functions in C++
Solution 1
Overhead is not an issue, namespaces have some advantages though
- You can reopen a namespace in another header, grouping things more logically while keeping compile dependencies low
You can use namespace aliasing to your advantage (debug/release, platform specific helpers, ....)
e.g. I've done stuff like
namespace LittleEndianHelper { void Function(); } namespace BigEndianHelper { void Function(); } #if powerpc namespace Helper = BigEndianHelper; #elif intel namespace Helper = LittleEndianHelper; #endif
Solution 2
A case where one might use class
(or struct
) over namespace
is when one needs a type, for example:
struct C {
static int f() { return 33; }
};
namespace N {
int f() { return 9; }
}
template<typename T>
int foo() {
return T::f();
}
int main() {
int ret = foo<C>();
//ret += foo<N>(); // compile error: N is a namespace
return ret;
}
Solution 3
To add to Pieter's excellent response, another advantage of namespaces is that you can forward declare stuff that you put in a namespace somewhere else, especially structs...
//Header a.h
// Lots of big header files, spreading throughout your code
class foo
{
struct bar {/* ... */);
};
//header b.h
#include a.h // Required, no way around it, pulls in big headers
class b
{
//...
DoSomething(foo::bar);
};
And with namespaces...
//Header a.h
// Big header files
namespace foo
{
struct bar {/* ... */);
}
//header b.h
// Avoid include, instead forward declare
// (can put forward declares in a _fwd.h file)
namespace foo
{
struct bar;
}
class b
{
//...
// note that foo:bar must be passed by reference or pointer
void DoSomething(const foo::bar & o);
};
Forward declares make a big difference to your compile times after small header changes once you end up with a project spanning hundreds of source files.
Edit from paercebal
The answer was too good to let it die because of an enum error (see comments). I replaced enums (which can be forward-declared only in C++0x, not in today C++) by structs.
Solution 4
The main advantage to using a namespace is that you can reopen it and add more stuff later, you can't do that with a class. This makes this approach better for loosely coupled helpers (for example you could have a Helpers namespace for your entire library, much like all of STL is in ::std)
The main advantage of a class is that you can nest it inside the class using it, you can't nest a namespace in a class. This makes this approach better for tightly coupled helpers.
You won't have any extra overhead having them in a class vs a namespace.
Solution 5
Namespaces offer the additional advantage of Koenig lookup. Using helper classes may make your code more verbose - you usually need to include the helper class name in the call.
Another benefit to namespaces is in readability later on. With classes, you need to include words like "Helper" to remind you later that the particular class isn't used to create objects
In practice, there's no overhead in either. After compilation, only the name mangling used differs.
Rob
C++, MFC, Win32, WTL, STL, Boost, HTML, CSS, JavaScript, Qt, Python, jQuery Mobile.
Updated on July 05, 2022Comments
-
Rob almost 2 years
While refactoring some old code I have stripped out a number of public methods that should actually of been statics as they a) don't operate on any member data or call any other member functions and b) because they might prove useful elsewhere.
This led me to think about the best way to group 'helper' functions together. The Java/C# way would be to use a class of static functions with a private constructor, e.g.:
class Helper { private: Helper() { } public: static int HelperFunc1(); static int HelperFunc2(); };
However, being C++ you could also use a namespace:
namespace Helper { int HelperFunc1(); int HelperFunc2(); }
In most cases I think I would prefer the namespace approach but I wanted to know what the pros and cons of each approach are. If used the class approach for example, would there be any overheads?
-
andrewmu almost 16 yearsActually you can't forward declare enums. Forward declaring of enums is a Microsoft extension and therefore not guaranteed to be portable.
-
ugasoft almost 16 yearsI agree with graham.reeds. you cannot fwd a enum, which size depends of actual values of emun labels
-
paercebal over 15 yearsWhoa... I DO believe namespaces ARE better than classes for this kind of problem, but your example is THE ONE example when classes have ONE advantage over namespaces. +1.
-
paercebal over 15 years(Note that I would still use namespaces over classes 99.99% the times anyway... but your comment is just the bit of information worth knowing)
-
paercebal over 15 yearsCorrect enum by struct. +1 anyway, because it is a very good reason, and that because I stumbled too much on the kind of code using classes instead of namespaces, and being forced to make a full include instead of a forward declaration.
-
jmucchiello over 15 yearsOr you can say #if powerpc \ using BigEndianHelper; \ #else ... This eliminates the qualifier whe calling the function. Something you can't do in a class (at global scope): Class::func
-
Drew Hall over 15 yearsIt's true that you can't nest a namespace in a class, but you can use an anonymous namespace in the class's CPP file with largely the same effect (or even a named namespace nested inside an anonymous one). Good answer though!
-
Tom over 15 yearsI would replace "one advantage" with "the only advantage".
-
peterchen over 15 yearsIteresting use for switching the "default" namespsaces, but keeping both implementations available.
-
Pieter over 15 years@joe, yes, but then the other implementation is no longer available. E.g. photoshop files are internally mainly BigEndian (irrespective of the platform), you can still use BigEndianHelper in functions that deal with photoshop files, and use 'platform' Helper at other places (just an example ;)
-
A. Howells about 5 yearsFor anyone else confused by the previous comments: It's been possible to forward declare enums for about a decade now. See here.