How to hide an implementation helper template?

后端 未结 5 2241
故里飘歌
故里飘歌 2020-12-15 05:21

Suppose that I have two template functions declared in a header file:

template  void func1(const T& value);
template          


        
相关标签:
5条回答
  • 2020-12-15 05:43

    A common approach (as used in many Boost libraries, for example) is to put the helper in a namespace called details, possibly in a separate header (included from the "public" header).

    There's no way to prevent it from being visible, and callable, but this quite clearly indicates that it is part of the implementation, not the interface.

    0 讨论(0)
  • 2020-12-15 05:43

    Since the user of your code needs to see the full definition of the func1 function, it's implementation, nor it's helper function implementation, can be hidden.

    But if you move the implementation into another file, the user will only have to be confronted with the template declaration:

    //templates.h
    template< typename T > void f1( T& );
    
    #include <templates_impl.h> // post-inclusion
    

    And the definition:

    // templates_impl.h
    template< typename T > void f1_helper( T& ) {
    }
    
    template< typename T > void f1( T& ) {
       // the function body
    }
    
    0 讨论(0)
  • 2020-12-15 05:50

    Two options off the top of my head:

    1. Move all the implementation to an hpp file which you include at the bottom of your h file.
    2. Refactor your code as class templates, then make the helpers private.
    0 讨论(0)
  • 2020-12-15 06:00

    I would (as said before) make a template class, make all functions static and the helper function private. But besides that I'd also recommend making the constructor private as shown below:

    template <typename T>
    class Foo{
    public:
      static void func1(const T& value);
      static void func2(const T& value);
    private:
      Foo();
      static void helper(const T& value);
    }
    

    When you make the constructor private, the compiler won't allow instances of this template class. So the code below would become illegal:

    #include "foo.h"
    
    int main(){
      int number = 0;
      Foo<int>::func1(number); //allowed
      Foo<int>::func2(number); //allowed
      Foo<int>::helper(number); //not allowed, because it's private
      Foo<int> foo_instance; //not allowed, because it's private
    }
    

    So why would someone want this? Because having different instances that are EXACTLY the same is something you probably never want. When the compiler tells you that the constructor of some class is private, then you can assume that having different instances of it would be unnecesarry.

    0 讨论(0)
  • 2020-12-15 06:01

    The established precedent is to put that sort of thing in a specially (i.e. consistently) named nested namespace. Boost uses namespace details, Loki uses namespace Private. Obviously nothing can prevent anyone from using the contents of those namespaces, but both names convey the meaning that their contents aren't intended for general consumption.

    That being said, an easy alternative is to turn func1 and func2 from free function templates into static member function templates of some common class; this way, helper can simply be a private member of said class, invisible to the outside world:

    struct funcs {
        template<typename T>
        static void func1(T const& value) {
            // ...
            helper(value);
        }
    
        template<typename T>
        static void func2(T const& value) {
            // ...
            helper(value);
        }
    
    private:
        template<typename T>
        static void helper(T const& value) {
            // ...
        }
    };
    
    0 讨论(0)
提交回复
热议问题