views:

109

answers:

1

I never really had a necessity for a global variable in a template (and actually I don't support a design like this very much) but this topic got me curious.

Even though answered, it inspired me trying a different approach. Instead of using inheritance, I came up with this:

class Bar {};

class {
private:
    Bar bar;
    template <class T> friend class Foo;
} static foobar_singleton;

template <class T> 
class Foo 
{ 
public:
    static Bar bar() { return foobar_singleton.bar; }
};

To me, the foobar_singleton works similarly to a 'non-member static private', since its content will be only acessible by the template class Foo. It also avoids inheritance though I am not sure this is an advantadge actually. My solution seems possible to be contained header-only, without necessity about another definition file.

I would like to see what are the opinions about this approach compared to the one utilized as an answer for the thread that got me curious. For instance, some examples of questions I'd like to hear about:

1. Do you see any clear advantadge in my example? Or for that matter, clear disavantadge?
2. Would you advice making bar attribute a static member and naming the class used as singleton?
3. This reminds any of you of any design pattern? Similar to pimpl idiom maybe?
4. You see any compiler portability problems? (I've tested it only with MSVC and GCC)
5. I'm right about being a possible header-only implementation? I'm actually not completely sure about the static variable foobar_singleton

Thanks in advance!

+2  A: 

The static variable foobar_singleton in your example will be a different variable in every translation unit (internal linkage!). Which is a kind-of a show stopper.

The inheritance in the original topic is only used to "inject" the common static variable into the namespace of the template. If that's not a requirement, just don't derive Foo from FooBase, works just as well.
If it's needed for whatever reason, I would derive privately, which should eliminate any possible side effects one could encounter from introducing an additional base-class. And of course add the helper-class as the last base-class, if Foo inherits other classes too.

If you want a header-only solution:

typedef int Bar;


template <class DummyType>
class FooCommonStatics
{
    static Bar s_bar;

    template <class T>
    friend class Foo;
};

template <class DummyType>
Bar FooCommonStatics<DummyType>::s_bar;

template <class T>
class Foo
{
public:
    // void is just a dummy-type, any type that's not dependent on T would do
    typedef FooCommonStatics<void> CommonStatics;

    Foo()
    {
        CommonStatics::s_bar++;
    }

private:
    T m_something;
};
pgroke
No need for a `DummyType`, you could just use the type its supposed to hold as the parameter.
Georg Fritzsche
You would have to use a template-template argument in FooCommonStatics to do that.
pgroke
No, `template<class Data> class Common { static Data s_bar; ...`.
Georg Fritzsche
OK, I think I misunderstood. Yes, you could do that. But since FooCommonStatics is tied to Foo anyway, that would not really make sense. OK, one could "reuse" the FooCommonStatics class to provide more than one static variable to Foo, if they all had different types, but well... I would find that even more confusing.
pgroke