Boost logo

Boost :

Subject: Re: [boost] [move] You can do it better: implementing push_back and handling implicit conversions
From: Stephan T. Lavavej (stl_at_[hidden])
Date: 2011-03-09 09:47:02


[Thomas Klimpel]
> Find attached a test case showing the scenario I described.
> This code actually really triggers the mentioned compile error.
> Standard wording can't help us here, because the standard doesn't
> say anything about dynamic link libraries. So I wouldn't see this
> as a bug, even if it is annoying at times.

By design.

C:\Temp>type meow.cpp
template <class T> struct container {
    T m;

    void forward_member_function() {
        m.member_function();
    }
};

struct b { };

#ifdef BOOM
    struct __declspec(dllexport) my_class : public container<b> { };
#else
    struct my_class : public container<b> { };
#endif

C:\Temp>cl /EHsc /nologo /W4 /c meow.cpp
meow.cpp

C:\Temp>cl /EHsc /nologo /W4 /c /DBOOM meow.cpp
meow.cpp
meow.cpp(5) : error C2039: 'member_function' : is not a member of 'b'
        meow.cpp(9) : see declaration of 'b'
        meow.cpp(4) : while compiling class template member function 'void container<T>::forward_member_function(void)'
        with
        [
            T=b
        ]
        meow.cpp(12) : see reference to class template instantiation 'container<T>' being compiled
        with
        [
            T=b
        ]

http://msdn.microsoft.com/en-us/library/81h27t8c.aspx says:

"Inheritance and Exportable Classes
All base classes of an exportable class must be exportable."

http://msdn.microsoft.com/en-us/library/twa2aw10.aspx says:

"the compiler changed the semantics of dllexport when it is applied to a class that has one or more base-classes and when one or more of the base classes is a specialization of a class template. In this case, the compiler implicitly applies dllexport to the specializations of class templates."

(This page is a little confusing because it was written when VS 2003 was new.)

When my_class is dllexported, its base class container<b> is explicitly instantiated and compiled into the DLL. That's why container<b>::forward_member_function() is being instantiated and subsequently exploding.

I'm not an expert when it comes to DLLs, but I can't imagine another way for this to physically work.

In the absence of dllexport, the compiler plays by the Standard rules that allow std::list<T> to work when T doesn't have op<(), as long as std::list<T>::sort() isn't called.

Stephan T. Lavavej
Visual C++ Libraries Developer


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk