-1

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

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

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

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

Throughout my code I instantiate these with various values of radix:

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

This works and doesn't create any hairy threading or API issues. But it's not sharing the radix table for 1 between myFoo and yourFoo. I could hardcode a dependency on an assumed thread library, and build a global map that's filled on-demand. But my question is:

"In the modern C++11 world, is there a clean way designing a library for Foo which does not have dependencies outside of the standard libraries?"

I thought of using a static member for this, since each separate instantiation of a template class creates only one static member variable. But this brings up the question of who is responsible for declaring the space for the static member and whoever does so has to "know the right 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's written on the subject like " C++ Static member initalization (template fun inside) " doesn't seem to turn up much hope...unless I'm missing something. Also, what would happen if Foo instances themselves were static? :-/

Community
  • 1
  • 1

2 Answers2

1

static members of templates won't work well across APIs if you want to ensure all instantiations of Foo<1> share the same table. This is because, going across module boundaries, if module A creates Foo<1> and module B creates Foo<1>, it will duplicate the static members.

I think your best bet is to map those integers to their corresponding tables at runtime.

I could hardcode a dependency on an assumed thread library, and build a global map that's filled on-demand. But my question is:

In the modern C++11 world, is there a clean way designing a library for Foo which does not have dependencies outside of the standard libraries?

As a practical answer, no, not yet. You need critical sections/mutual exclusion for your table if you want thread safety (unless you can manage to make a shared container that is thread safe and lock-free with no third party dependencies) and there's nothing out of the box in C++11 that's implemented yet (at least in popular compilers) to give you cross-platform concurrency AFAIK.

In the future, C++11's concurrency features will support mutexes and atomics out of the box, but popular compilers haven't implemented this feature yet to my knowledge.

stinky472
  • 6,737
  • 28
  • 27
  • +1 and thanks for the response. It has taken me a while to get back to and try and process the example I'm working with. I have a gut feeling that what @J.N. suggests isn't actually changing anything, yet it is making a previously uncompilable situation compile...so I'd be curious what your answer would say if you were to take that nuance into account! – HostileFork says dont trust SE Mar 06 '12 at 05:19
1

First, there's a standard thread library in C++11 you can rely on according to your own definition.

Then, you should mention that what you need as name: it's a singleton.

Finally, there's a way in C++11. The language is aware of threads, and as such, static variable initialization 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 have mentioned a few fair points in the comments. Here is an answer better for your needs, I hope. Actually, the fact that FooLookup create templated foos is not useful to solve the problem. It confused me a bit, you don't need any 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 the function thread safe. My bad. It seems my first solution may be better for you after all. There is a solution without <mutex> if you know (at compilation time) the list of the radixes for which you want to create a lookup table.

Community
  • 1
  • 1
J.N.
  • 8,203
  • 3
  • 29
  • 39
  • I'm perplexed by the idea that moving the static variable inside a static class function would change anything at a fundamental level. Intuitively I would think it would not offer any benefit over a class-static member other than that the constructor execution is delayed to run only the first time the function runs. (Though this could be done other ways.) Yet whether this is *actually* addressing what @stinky472 and I are concerned about, the technique seem to finesse error messages I couldn't get past with statics that don't live in functions doing this with templates. Huh? +1 for that. – HostileFork says dont trust SE Mar 06 '12 at 05:17
  • I will however point out that my sample did not have `Foo` for a given `` as a singleton. If it were, then `myFoo` and `yourFoo` should be the same object. Instead there is a "singleton" `FooLookupTable` for each ``. It would probably help illustrate your point if your example were cast more precisely parallel to terms of the scenario laid out in the question...! :-/ – HostileFork says dont trust SE Mar 06 '12 at 05:23
  • @HostileFork : fair points. Please see edited answer above. I think it is what you want this time. – J.N. Mar 06 '12 at 06:14
  • An important precision, when I say "thread safe", I mean that the _creation_ of the object is thread safe (only one copy), not its usage. – J.N. Mar 06 '12 at 06:57
  • 1
    Thank you for the updates. I looked up and linked an SO citation in your answer for the thread safety of static initialization. Also, here's a lengthy related article debating the situation in the old standard and different compilers: http://blogs.msdn.com/b/oldnewthing/archive/2004/03/08/85901.aspx – HostileFork says dont trust SE Mar 06 '12 at 21:17
  • I think the "answer" is that from a technical standpoint one does need to do this at runtime if you want the tables to be *truly* one per instance (instead of one per module instance that invokes the template for a given value). Yet using statics inside a member function instead of as members themselves helped with the "API mitigation" and is good enough for my case, so thanks again for that idea. The only question is if it's *actually* thread-safe...here's a follow up: http://stackoverflow.com/questions/9608257/do-any-c11-thread-safety-guarantees-apply-to-third-party-thread-libraries-comp – HostileFork says dont trust SE Mar 09 '12 at 06:10