How to reduce user API effect of common members in template classes?

Let's say I have a type of lookup table that I can build for a given integer:

class FooLookupTable { ... public: FooLookupTable(int radix) { ... } }; 

Then there is a class whose template parameter is the same integer, and whose constructor initializes the member instance of this lookup table:

 template <int radix> class Foo { ... private: FooLookupTable table; public: Foo () : FooLookupTable (radix) { ... } }; 

In my code, I create them with different radix values:

  int main() { ... Foo<1> myFoo; Foo<1> yourFoo; Foo<10> theirFoo; ... } 

This works and does not create any problems with the hair or API. But he did not divide the radix table by 1 between myFoo and yourFoo . I could hard code the dependency on the proposed library of threads and build a global map filled on demand. But my question is:

"In the modern world of C ++ 11, is there a clean way to develop a library for Foo that has no dependencies outside standard libraries?"

I was thinking of using a static member for this, since each individual instance of the template class creates only one static member variable . But this raises the question of who is responsible for declaring space for the static member and whoever does this should β€œknow the correct way to initialize it”:

  FooLookupTable Foo<1>::table (1); FooLookupTable Foo<10>::table (10); int main() { ... Foo<1> myFoo; Foo<1> yourFoo; Foo<10> theirFoo; ... } 

Reading what is written on a topic like C ++ Static initalization membership (boilerplate fun inside) "doesn't seem to be very hopeful ... if I don't," something is missing. Also, what happens if the Foo tags themselves were static ?: - /

-one
c ++ templates lookup-tables
source share
2 answers

static template elements will not work well in the API if you want all instances of Foo <1> to share the same table. This is because, crossing the boundaries of the modules, if module A creates Foo <1> and module B creates Foo <1>, it will duplicate static elements.

I think your best bet is to match these integers with your respective tables at runtime.

I could hard code the dependency on the proposed library of threads and build a global map filled on demand. But my question is:

In the modern world of C ++ 11, is there a clean way to develop a library for Foo that has no dependencies outside the library standard?

As a practical answer, no, not yet. You need critical sections / mutual exclusion for your table, if you need thread safety (unless you can create a shared container that is thread safe and unlocked without any third-party dependencies), and in C ++ there is nothing out of the box 11 which is still implemented (at least in popular compilers) to provide you with cross-platform concurrency AFAIK.

In the future, C ++ 11 concurrency functions will support mutexes and atomics out of the box, but popular compilers have not yet implemented this function, as far as I know.

+1
source share

First, C ++ 11 has a standard thread library that you can rely on according to your own definition.

Then you must specify what you need as a name: this is singleton.

Finally, there is a way in C ++ 11. The language knows about threads, and as such a static initialization variable is thread safe :

 template <int radix> class Foo { public: // your public stuff, no contructors static Foo& GetInstance() { static Foo instance(...); // thread safe accoding to C++11 return instance; } private: Foo(...) { } } 

EDIT:

You mentioned some great comments in the comments. Hope this is the best answer for your needs. In fact, the fact that FooLookup creates templated foos is not useful for solving the problem. It confused me a bit, you do not need templates for this.

 // Header file class FooLookupTable { public: // needed to use with map FooLookupTable() { } FooLookupTable(int index) { } static FooLookupTable& GetLookup(int index); }; // CPP file (no library boundary problem since this file will be linked only once) // I fear I can't do that without using a mutex explicitely, but those are in the standards. // You'll need a recent compiler to support them (GCC 4.5 and MSVC11) #include <mutex> using namespace std; FooLookupTable::FooLookupTable& GetLookup(int index); { static map<int, FooLookupTable> _tables; // thread safe in C++11 static mutex _m; // The function body isn't thread safe though, so we need to protect it. lock_guard<mutex> l(_m); // make sure we don't create the same one twice. auto it = _tables.find(index); if (it == _tables.end()) { _tables[index] = FooLookupTable(index); return _tables[index]; } else return *it; } 

EDIT 2

Made a thread safety function. To blame. It seems my first decision may be better for you in the end. There is a solution without <mutex> if you know (at compile time) a list of the bases for which you want to create a lookup table.

+1
source share

All Articles