Seperating material between header and '.cpp' files.

While programming in the past I have always tried to keep my headers and implementation files (if that is the proper name for the '*.cpp' files!) as separate as possible. Therefore I only included either struct, enum, class, function or global variable declarations in the header file. I appreciate that one way to manually declare an inline class member function is to put the definition directly inside the class declaration. However--again, in the past--if I specifically wanted a function to be considered for this optimization I would add the 'inline' reserved word to the beginning of the function definition in the *.cpp file.

This always seemed to work pretty well until I recently returned to hobby programming after a lengthy break and decided I would made the effort to begin learning how to use templates properly. In the course of this I have discovered using the split '*.h' and '*.cpp' model does not work for templated classes and functions. Indeed, if you try to do it this way the compiler reports very hard to understand errors! Going from replies in this forum and other places I got the impression that for templates you pretty much have to always write your functions and member functions as inline--that is directly inside the header file or class declaration. I understand there is a dodge where you can write the function definitions in a '*.tpp' file and the use '#include' preprocessor directive after the class declaration in order to include them to the header... Which feels very strange and a little cumbersome!

However, just as I was getting used to putting everything in to the header--which if nothing else seemed to help with the weird behaviour of Visual Studio Intellisense when working with templates--I now read that the advice from the people who are in charge of the C++ language is that 'interface and implementation' programming should be kept strictly separate, which I take to mean as going back to old '.h' for definitions and '*.cpp' for declarations...

Honestly I am a bit lost on this issue!

Is there some way to make templates work in that model? Am I (very likely!) misunderstanding the C++ committee guidance altogether?
I am not a super expert but templates used to be a special thing that had to be coded in the headers in most/many cases. If that is still true, you just have to deal with this oddity of the language.
See: 'Why can’t I separate the definition of my templates class from its declaration and put it inside a .cpp file?'
https://isocpp.org/wiki/faq/templates

And: 'Explicit instantiation' http://en.cppreference.com/w/cpp/language/class_template
An explicit instantiation declaration (an extern template) skips implicit instantiation step: the code that would otherwise cause an implicit instantiation instead uses the explicit instantiation definition provided elsewhere (resulting in link errors if no such instantiation exists). This can be used to reduce compilation times by explicitly declaring a template instantiation in all but one of the source files using it, and explicitly defining it in the remaining file.
I now read that the advice from the people who are in charge of the C++ language is that 'interface and implementation' programming should be kept strictly separate, which I take to mean as going back to old '.h' for definitions and '*.cpp' for declarations...


Hi,

I think what they are talking about there is to have an Abstract Base Class (ABC) which contains pure virtual functions and perhaps some ordinary virtual functions. This class is the interface, the implementation is in the derived classes.

That can be extended, one can have multiple interfaces to your class.

https://isocpp.org/wiki/faq/multiple-inheritance

The above link talks about other things such as the Bridge Design Pattern, and Nested Generalization.


Good Luck !!
Last edited on
Many thanks for all your suggestions guys!!!

This is a real brain twister for me and sometimes the technical definitions of these features leave me more confused than before! I once made the mistake of buying the definitive reference text on C++ written by that Danish chap who invented it... Wow... It honestly almost put me off programming! Or at least made VB seem quite attractive! It was really, really hard to follow, but made an excellent bathroom reader! On that note I am glad that it seems everyone considers the 'isocpp.org' site as reliable since I go their a lot and find the answers he gives to be be very helpful and pitched at a level I can understand.

Therefore, after mulling all this information I think I was pretty much doing the right thing before--all template functions need to be both declared and defined in the header file or at very best use the #include "*.tpp" dodge if you really want to separate them physically while you are writing them. It is a real shame that use of 'export' which the "Comeau' programming language offered did not take off and make it into the standard as it sounds like it would have solved the problem properly. Never mind!

I am quite interested in starting to write COM programmes once I have got templates at least partially nailed down in my mind. This business of 'implementation and interface' seems to ring a bell from when I was reading about COM long ago.
> It is a real shame that use of 'export' which the "Comeau' programming language offered
> did not take off and make it into the standard

It was part of the standard in C++98.
The front end for the Comeau compiler is (was?) the EDG front-end which had implemented export.

However
... the committee considered the question of whether to deprecate, remove, or leave in the “export template” feature.

For context, the only reason we’re even considering this is because Edison Design Group (EDG), the only company to ever implement export, is recommending export be removed or deprecated. Recall that back in the 1990s the committee originally voted the feature in over EDG’s objections in the first place, then in the late 1990s and early 2000s EDG graciously and gallantly went on to invest enormous effort to implement the feature in order to conform to the standard, and so the committee was loath to punish them again by now removing the feature on them. However, given the passage of time, EDG reports that their experience in the field has been that nearly no one actually uses the feature, and that it would be right (and okay with EDG) to deprecate or remove it.

At our previous meeting, the general sentiment was in favor of deprecation only. However, at this meeting EDG reported that they would prefer the feature to be removed rather than just deprecated, because a deprecated feature is still part of the standard and required for conformance. By removing it from C++0x, it removes the maintenance burden of being forced to support export indefinitely to maintain full standards conformance (though of course EDG will continue to support it as an extension in their compiler front end for however long seems right based on their own customers’ demand).

The committee agreed, and today voted to remove export entirely from C++0x. The “export” keyword is still reserved for future use, but has no defined meaning in the C++0x standard.
https://herbsutter.com/2010/03/13/trip-report-march-2010-iso-c-standards-meeting/
That makes fascinating reading JLBorges! From what that chap writes it sounds like 'export' for templates was a real pig to implement.

Maybe something different will come along in the future to make templates easier to write.
See: 'Why can’t I separate the definition of my templates class from its declaration and put it inside a .cpp file?'
https://isocpp.org/wiki/faq/templates

And: 'Explicit instantiation' http://en.cppreference.com/w/cpp/language/class_template

I have just read through those extracts you linked to for a second time JLBorges. I still think I shall (re)adopt the method which seems most general--write templated class member-function definitions inside their own header file. However the web-master of 'ISOCPP.COM' mentions that doing so may add a lot of bulk to any programme in which I use that template . He also says it may not and the programmer should test it out...

I only have one version of C++ available--the free Visual Studio 2017 Community edition--and cannot experiment with how this technique effects the 'code bloat'. I don't suppose you know how this plays out using different compilers do you?
> However the web-master of 'ISOCPP.COM' mentions that doing so
> may add a lot of bulk to any programme in which I use that template

Let us say we have two versions of the code, with both versions having identical functionality,
written in an identical manner, using the same programming constructs:
a. version T written using templates
b. version C written without using templates

For example, in version T, we have:
template < typename T > struct my_class<T> { /* complex code, some inline and others non-inline */ };
and in our program we instantiate my_class<int>, my_class<double>, my_class<A>, my_class<B>, my_class<C>

In version C, we have the non-template classes:
struct my_class_int { /* complex code, some inline and others non-inline */ };,
struct my_class_double { /* complex code, some inline and others non-inline */ };,
struct my_class_A { /* complex code, some inline and others non-inline */ };,
struct my_class_B { /* complex code, some inline and others non-inline */ };,
struct my_class_C { /* complex code, some inline and others non-inline */ };

Assuming that the optimiser would determine that our non-inline functions can't be profitably inlined
(or we disable automatic inlining of non-inline functions with a compiler option):
The generated code size for the two versions would, at worst, be very close.
In practice, the generated code size would be less for version T (template).
That sounds pretty categorical - I shan't worry about it any more then!

One question I do have after reading your example--why do you declare your class using the struct reserved word? Can a struct have member-functions too?
Last edited on
> Can a struct have member-functions too?

Yes.

In a class declaration, the keywords class and struct are synonyms, except that:
With the keyword class, the default member-access (and the default base-class-access) is private
With the keyword struct, the default member-access (and the default base-class-access) is public

class A { public: /* ... */ }; and struct A { /* ... */ }; are equivalent.

class B { /* ... */ }; and struct B { private: /* ... */ }; are equivalent.


> why do you declare your class using struct

I tend to place the declarations of public members of a class at the beginning; so using struct instead of class is convenient.

Unless there is a coding guideline in effect, which insists that programmers should treat the non-distinction between struct and class as if there was a distinction. For instance:
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c2-use-class-if-the-class-has-an-invariant-use-struct-if-the-data-members-can-vary-independently
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c8-use-class-rather-than-struct-if-any-member-is-non-public
Yes.

In a class declaration, the keywords class and struct are synonyms, except that:
With the keyword class, the default member-access (and the default base-class-access) is private
With the keyword struct, the default member-access (and the default base-class-access) is public


Absolutely fascinating!!! You really can learn something new every day if you try. I've been pottering around with C++ since early August in 1986 and I never, ever realized that!!! I guess it is because I came to the language from C that I just assumed structures were for data only. Weird it never occurred before now!

Anyway--I am going to mark this question as 'answered' as I think it has covered every area I wondered about. Many, many thanks to everyone who replied. However, going from this example I am sure I will have a ton more absolute-beginner's C++ questions to ask!
Topic archived. No new replies allowed.