This seems to be a most economical idiom for what's on the ExtremeFormsForCppCode
page ... but it also seems badly broken right now. Our cracked team of wiki investigators are investigating ...
The upshot is described on ExtremeCppFormTest
is that while you can get this form around the compiler eventually, you can't safely derive from it. Dead end?
// Public interface for Class Foo
template <int> struct FooIF
void setBar(int const & i);
typedef FooIF<0> Foo;
// Private implementation of Class Foo
template struct FooIF<0>
void setBar(int const & i)
m_bar = i;
// Demonstrate that the linker can connect interface to implementation - as
// far as a user's concerned they just have a class Foo.
This is sort of an StlStyle
technique - no factories, no vtables and hang that hokey public/private stuff. Whoever said you can't do Java interfaces in C++ was a slacker.
This should run fine on any reasonably modern C++ compiler. Note that it's not polymorphic. I'm thinking that maybe the template argument could maybe be used to differentiate between builds for various platforms, but really this idiom is just about insulation. -- PeterMerel
Maybe this doesn't qualify as reasonably modern, but MSVC 6.0 seemed to choke on this. Maybe I messed something up... -- BrianMosher
D'oh! My fault - I twiddled the method signature to follow Dave on DontUseGetAndSet, and screwed up the method name: setBar and Setbar. Try with both the declaration and the definition of the method set to the same name as corrected above.
I tried to compile this program and I'm not getting it to work. I changed the SetBar?
to setBar. Both main.cpp and foo.cpp compile, but link reports that FooIF<0>::setBar is not there. This is with both egcs and KCC (KAI C++). I suspect that some template instantiation operator is needed. It was also necessary for me to modify the template specialization to:
template<> struct FooIF<0>
VC++ didn't make it past the typedef. Are you sure you got this to work Peter? It really shouldn't. The linker has no business fixing up the size of objects that are allocated on the stack and the compiler has no business remembering stuff from one compilation unit to the next. -- PhilGoodwin
I am sure that this, or one that ought to be functionally identical, worked perfectly under VS6 - I stuffed some output to cout and I saw it just fine. But I am concerned that the build environment I used - OSE Makeit - may have set some kind of compile/link settings that enabled that to work for me. I can't recheck this till the a.m. - I'll update this page asap then. Apologies for the suspense.
As to how it works, I believe that the .cpp results in the compiler creating code for the specialized template, which of course is preferred to the generic. The compiler certainly remembers nothing from one compilation unit to the next. The linker simply looks for a definition of the method called in main.cpp and finds it in the .obj generated from foo.cpp. Or else I've gone mad, but I haven't ever been quite this mad before, I promise. I'll build it as a VS project in the a.m. and put it some place accessible to all.
My results (JohnClonts
) egcs 1.1.2: "(error) foo.cpp:10: definition provided for explicit instantiation". On VC6 at warning level 3 "foo.cpp(15) : warning 4660: template-class specialization 'FooIF<0>' is already instantiated; foo.cpp(8) : see declaration of 'FooIF<0>'"
I tried it again this morning without success but with some interesting results. I wrote an ExtremeCppFormTest
to check out whether the whole object was actually being allocated and whether I could inherit from the result. I'll put my results on that page. -- PhilGoodwin
I confess I'm mystified at the problems VC6 is giving folk - I've pasted the contents into the VC6 IDE exactly as written here and got a good build with just the default compile/link settings. I did see the warning JohnClonts quotes above, but it does compile, link and run as advertised. I'm running Compiler Version 12.00.8168 (without patches I think) - you can check the version by typing "cl" at the command prompt.
I do get a failure with GnuCpp though - I'll tinker a bit and see what its notions on template specialization are about. Also might be high time to crack open Stroustrup.
Better still, the Standard. Clause 22.214.171.124 says If a template, a member template or the member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.
This code appears to break this rule. -- BenHutchings
Perhaps it would be sufficient to get the code in ExtremeCppFormTest
to work. I'm not worried about the compiler warning, it's the bit about overwriting the stack that sort of bugs me. -- PhilGoodwin
Yes, that is a slight drawback ... -- PM
You know, I've been hanging back, but I think that the vtables are rather important. - mf