Link to home
Start Free TrialLog in
Avatar of kfcox
kfcox

asked on

Template member functions of template classes in DLL's

I've learned how to export specific instances of a template class from a DLL, but I now have a problem involving a template class that has a template member function. Here's a simple example: suppose I have a template class Foo, as follows:


// Foo.h
#ifdef BUILDING_FOO
#define EXPORT_TEMPL
#define TEMPL_DECL __declspec(dllexport)
#else
#define EXPORT_TEMPL extern
#define TEMPL_DECL __declspec(dllimport)
#endif

template <class T>
class Foo {
public:
    Foo() { }
    virtual ~Foo() { }
    template <class A>
    static void DoIt( A* pA, T t ) {
        m_datum = t;
        pA->doit(t);
    }
    static T m_datum;
};

EXPORT_TEMPL template class TEMPL_DECL Foo<int>;

// Foo.cpp
int __declspec(dllexport) Foo<int>::m_datum = 123;


Foo has a static data member and a static (template) member function. I export Foo<int> from the DLL, and I have no problem getting clients of the DLL to resolve Foo<int> during linking. I do have a problem accessing Foo<int>::DoIt() however:


// main.cpp
class Bar {
public:
    void doit( int i ) {
        cout << "Bar::doit: i = " << i << endl;
    }
};
void main()
{
    Bar bar;
    Foo<int> foo;
    cout << "foo.m_datum = " << foo.m_datum << endl; // OK
    foo.DoIt( &bar, 456 ); // link err: can't find in DLL
}


The problem is, the linker can't find Foo<int>::DoIt<Bar>() in the DLL. Obviously, this can't be exported from the DLL since Bar is defined by the client and is unknown to the DLL. Is there any way of exporting Foo<int> without exporting the DoIt() template member function so that client code will just instantiate DoIt() during its compilation?
What are my alternatives? (I don't want to turn DoIt() into a non-template member function).
I'm using Visual C++ 5.0 on NT 4.0.
Avatar of anichini
anichini

I'm pretty sure that VC++ 5.0 doesn't support member templates anyway, so the question is moot, no?

Avatar of kfcox

ASKER

I've gotten (simple) member templates (such as the one shown in the example I gave) to work just fine ... when there is no DLL exportation involved. What I really need to do is export the static class member variables without exporting the member functions ... and in a way that allows importing the static member variables into clients. For example, if I define Foo as:

template <class T>
class Foo {
public:
    Foo() { }
    virtual ~Foo() { }

    template <class A>
    static void DoIt( A* pA, T t ) {
        m_datum = t;
        pA->doit(t);
    }
    static TEMPL_DECL T m_datum;  // *** export/import m_datum
};


... I'm able to use Foo in clients fine, but the problem that is still hanging me up is that I'm unable to export some other instance of Foo from a separate DLL. In other words, if Foo is defined as part of Foo.DLL (and Foo<int> exported from it), I'm not able to export Foo<something_else> from a separate DLL, say FooUser.DLL because the TEMPL_DECL macro used in specifying m_datum is defined to be __declspec(dllimport) during compilation of FooUser.DLL. Am I making any sense? What I really need to be able to do is export Foo<something_else> from FooUser.DLL!!

ASKER CERTIFIED SOLUTION
Avatar of mnguyen021997
mnguyen021997

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
You can try putting the export syntax ahead of every non-template member of the template class in the class declaration. Then make the template member inline. Then use the EXPORT_TEMPL for each non-template member