Safely use containers in C++ library interface

前端 未结 4 987
予麋鹿
予麋鹿 2021-02-02 00:28

When designing a C++ library, I read it is bad practice to include standard library containers like std::vector in the public interface (see e.g. Implications of us

4条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2021-02-02 00:43

    You can implement a template function. This has two advantages:

    1. It lets your users decide what sorts of containers they want to use with your interface.
    2. It frees you from having to worry about ABI compatibility, because there is no code in your library, it will be instantiated when the user invokes the function.

    For example, put this in your header file:

    template 
    void foo(Iterator begin, Iterator end)
    {
      for (Iterator it = begin; it != end; ++it)
        bar(*it); // a function in your library, whose ABI doesn't depend on any container
    }
    

    Then your users can invoke foo with any container type, even ones they invented that you don't know about.

    One downside is that you'll need to expose the implementation code, at least for foo.

    Edit: you also said you might want to return a container. Consider alternatives like a callback function, as in the gold old days in C:

    typedef bool(*Callback)(int value, void* userData);
    void getElements(Callback cb, void* userData) // implementation in .cpp file, not header
    {
      for (int value : internalContainer)
        if (!cb(value, userData))
          break;
    }
    

    That's a pretty old school "C" way, but it gives you a stable interface and is pretty usable by basically any caller (even actual C code with minor changes). The two quirks are the void* userData to let the user jam some context in there (say if they want to invoke a member function) and the bool return type to let the callback tell you to stop. You can make the callback a lot fancier with std::function or whatever, but that might defeat some of your other goals.

提交回复
热议问题