Search code examples
c++design-patternstemplatesboostshared-ptr

C++ Templates - How to use across multiple MTU's


class A : boost::noncopyable {
    int type;

    A(int type, enum e) : type(type) { /* ... */ }
}
typedef boost::shared_ptr<A> A_ptr;


template <enum VAR>
class B : boost::noncopyable {
    static A_ptr x, y;

    B() {
        if (!x.get()) {
            x.reset(new A(0, VAR));
        }
        if (!y.get()) {
            y.reset(new A(1, VAR));
        }
    }
}

I want to have several types of 'B' based on the template ; that way it will keep separate statics and 'tracking' of their own x, y (A_ptrs).

The Question(s):

a) How do I set this up into a header/source configuration, with the templates working correctly?

b) Should I form a 'createA' function instead of the x.reset(new A(0, VAR));

c) Is the shared_ptr.get() guaranteed to return 0 (ie false in a boolean expression) when uninitialized?

Should I split b) and c) across multiple SO questions?


Solution

  • a) Set it up like this:

    A.h:

    #ifndef A_HEADER_GUARD
    #define A_HEADER_GUARD
    
    class A {...};
    
    #endif
    

    A.cpp:

    // A::method1 implementation
    // A::method2 implementation
    // etc...
    

    B.h:

    #ifndef B_HEADER_GUARD
    #define B_HEADER_GUARD
    
    #include "A.h"
    
    template <enum VAR> class B {...}
    
    #endif
    

    Note that class B can't be implemented in a cpp file. This is because class B is a template and its implementation must completely visible to whoever instantiates the template.

    Make sure you understand the use of header guards (aka include guards).


    b) Writing private helper methods to "factor out" frequently repeated code is quite normal, and I'd say even encouraged.


    c) Yes, shared_ptr::get() is guaranteed to be 0 when uninitialised, as stated in the postconditions clauses in the documentation.

    Instead of checking shared_ptr::get() in a condition expression, you can just check the shared_ptr itself. It automatically converts itself to bool when used in a boolean context. For example:

    shared_ptr<A> a_ptr;
    if (!a_ptr)
        cout << "a_ptr not initialized!";
    

    This is the idiomatic way of checking smart pointer validity.