Namespaces and C ++ Templates

I have some functions that can be grouped together, but do not belong to some object / entity and therefore cannot be considered as methods.

So, basically in this situation, I would create a new namespace and put the definitions in the header file, the implementation in the cpp file. Also (if necessary) I would create an anonymous namespace in this cpp file and put all the extra features that should not be included / included in my namespace interface there.

See the code below (maybe not a good example and might be better with a different software architecture, but I just can't come up with a better example ...)

Sample code ( header )

 namespace algorithm { void HandleCollision(Object* object1, Object* object2); } 

Sample Code ( cpp )

 #include "header" // Anonymous namespace that wraps // routines that are used inside 'algorithm' methods // but don't have to be exposed namespace { void RefractObject(Object* object1) { // Do something with that object // (...) } } namespace algorithm { void HandleCollision(Object* object1, Object* object2) { if (...) RefractObject(object1); } } 

So far so good. I think this is a good way to manage my code, but I don’t know what to do if I have some template-based functions and want to do basically the same thing.

If I use templates, I have to put all my code in a header file. Ok, but how should I hide some implementation details?

I want to hide the RefractObject function from my interface, but I can’t just delete its declaration (just because I have all my code in the header file) ...

The only approach I came up with is something like:

Sample code ( header )

 namespace algorithm { // Is still exposed as a part of interface! namespace impl { template <typename T> void RefractObject(T* object1) { // Do something with that object // (...) } } template <typename T, typename Y> void HandleCollision(T* object1, Y* object2) { impl::RefractObject(object1); // Another stuff } } 

Any ideas how to do this better in terms of code design?

+6
c ++ design namespaces templates
source share
4 answers

This is a fairly common solution. Boost does this, and I do it as well, but instead of detail. Just make this rule: "don't look inside detail !"

According to the files, I recommend providing the details of their own file and filling it in the folder with detailed information. That is, my code will be akin to:

 // v #include "detail/RefractObject.hpp" namespace algorithm { template <typename T, typename Y> void HandleCollision(T* object1, Y* object2) { detail::RefractObject(object1); // Another stuff } } 

This is just good practice for the code as a whole (keep things separate and reusable) and keep the header file cleaner in implementation details.

+7
source share

Create a "static class" - instead of a namespace, declare a class with the same name. Make the constructor, destructor, copy, and assignment operations private, then make each of your autonomous functions a static member function.

Template example:

 template<class T> class StringOperator { friend SomeOtherLibraryClass; // Let it use "Hidden()" private: StringOperator() {} ~StringOperator() {} StringOperator(const StringOperator&); StringOperator& operator=(const StringOperator&); static bool Hidden(const T& input) { // Hidden routine end-users shouldn't see... } public: static void YourFunction(T& parameter) { // Some public code.... } static T AnotherRoutine(const T* ptr) { // Some public code... } }; 

Here are some advantages against a namespace:
1) You can create a template for the entire class, ensuring that you have a version of each function for each type - you can even specialize in adding / removing functions based on the type.
2) You have a private area where you can hide ads for non-public objects and methods that you need
3) Through the friend mechanism, you can allow other objects, such as SomeOtherLibraryClass, to use their functions without exposing them to end users.

End users can access functions using "StringOperator :: FunctionName ()", or you could use templates instead to provide "StringOperator :: FunctionName ()". The latter is the same template that they will use to access functions in the namespace.

+2
source share

You cannot hide your source from the user unless you compile it first, which is not possible with templates. Therefore, I suggest, in a sense, that you are not worried.

You also need to ask why Refract cannot be a member method.

+1
source share

I was thinking the same thing. in the end, I decided to use classes to make the code more portable, reusable, and generic.

  • Classes
  • allow you to do all kinds of metaprograms such as traits, tag dispatching, and policies.
  • classes already have open, closed and protected.

there are only two reasons why you would use a namespace:

  • to resolve name conflicts std::for_each vs boost::for_each
  • to reduce visual noise. for example using namespace boost::filesystem , allows you to simply call its function without :: .

even for these two cases, you can either inherit a class that has methods, or rename it by initiating ( my_own_filesystem_methods fs; and this is like fs.mkdir() . plus fs.mkdir() shorter than :: .

there are other advantages of namespaces, such as std::cout << "hi" << endl; but it’s not very important.

0
source share

All Articles