1

I pursued the PImpl design to avoid having to export STL from my dynamic library.

Old:

//In header file
class Foo{
public:
    const map<char, char>& getMap() {return _map;}
private:
    map<char, char> _map;
};

New:

//In header file
class Foo{
public:
    Foo();
    ~Foo();
   const map<char, char>& getMap();
private:
    struct Impl;
    Impl* _pimpl;
};

//In implementation file
struct Foo::Impl{
    map<char, char> _map;
}
Foo::Foo(): _pimpl(new Impl){}
Foo::~Foo(){delete _pimpl;}
const map<char, char>& Foo::getMap(){return _pimpl->_map;}

However the clear issue is that I still have to export the map as part of my library. I don't want to stop returning STL, but I don't see a way around it. Is there another paradigm which will still let me return STL but not have to export it?

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • The only way is not to include stl headers in your headers. Then you can't use stl classes in the headers – BЈовић Feb 18 '15 at 13:10
  • 2
    If you do not wish to export the map then provide a find method in Foo or a function to do whatever you are going to use the map for. – cup Feb 18 '15 at 13:23
  • @BЈовић So when you say, "The only way is not to include stl headers in your headers." What you mean is, "There's not a way to return STL from your library without exporting." Right? – Jonathan Mee Feb 18 '15 at 13:43
  • Right. The pimpl idiom is not going to help either, since you have a method returning `std::map` – BЈовић Feb 18 '15 at 14:54

1 Answers1

1

A solution is to not use std::map in the interface of your class, but rather, implement the requires subset of methods. For example, assuming you want read-write element access via operator[],

// Foo.h
class Foo{
public:
    Foo();
    ~Foo();
   const char& operator[](char key) const;
   char& operator[](char key);
private:
    struct Impl;
    Impl* _pimpl;
};

then

// Foo.cpp
#include <map>
struct Foo::Impl
{
    std::map<char, char> _map;
};

Foo::Foo() : _pimpl(new Impl){}

Foo::~Foo(){delete _pimpl;} // don't forget to take care of copy and assignment

const char& Foo::operator[](char key) const {return _pimpl->_map[key];}

char& Foo::operator[](char key) {return _pimpl->_map[key];}
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • @jaunchopanza This is actually a really clever solution. It doesn't get me everything I want, like STD Algorithm support, but I suppose that I could cut holes for anything that I need... – Jonathan Mee Mar 28 '15 at 12:28
  • 1
    @JonathanMee Maybe you can export some kind of "any iterator" that hides the underlying type (see this [any_iterator](http://thbecker.net/free_software_utilities/type_erasure_for_cpp_iterators/any_iterator.html) implementation, or use boost.iterator to implement one.) – juanchopanza Mar 28 '15 at 15:23