2

In a project I'm working on, I have a fairly large templated class that I've implemented like this:

I have my header file

// MyBigClass.h
#ifndef MYBIGCLASS_H
#define MYBIGCLASS_H

template <typename T>
class MyBigClass {
   /* -- snip -- */
};

#include "MyBigClass.cpp"
#include "MyBigClass_iterator.cpp"
#include "MyBigClass_complicatedFunctionality_1.cpp"
#include "MyBigClass_complicatedFunctionality_2.cpp"

#endif

And then all of my implementation files look basically like this:

// MyBigClass_foobar.cpp

template <typename T>
void MyBigClass<T>::member_1(){
   /* -- snip -- */
}

template <typename T>
int MyBigClass<T>::member_2(int foo, T & bar){
   /* -- snip -- */
}

// etc, etc

In main.cpp, I just include MyBigClass.h, and everything works and compiles fine. The reason I've split the implementation into many files is because I prefer working on three or four 200-400 line files, versus one 1200 line file. The files themselves are fairly logically organized, containing for example only the implementation of a nested class, or a group of interrelated member functions.

My question is, is this something that is done? I got a strange reaction when I showed this to someone the other day, so I wanted to know if this is a bad practice, or if there is a better, more usual way to accomplish something like this.

Gordon Bailey
  • 3,881
  • 20
  • 28

4 Answers4

5

It's convention to generally not include cpp files (there are limited and exotic cases when this is done), that's probably the reason you got the weird looks.

Usually this separation is done by moving the implementation to an .impl or even a .h file instead of a cpp file.

And no, there's nothing wrong with separating the implementation of templates and including the file in the header.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
4

So... include .cpp is a bad practice, but what prevent you from using header files instead of .cpp? boost use .ipp files for example...

ForEveR
  • 55,233
  • 2
  • 119
  • 133
2

Having worked on C/C++ projects with thousand or more files, this is the practice I've generally observed:

  1. Keep the class definitions in the header file. Do not add any implementation in the header file. The exceptions being inline functions and templates. I'll come to that in the end.
  2. Keep all of your function and method implementations in .c or .cpp files.

There are fundamental reasons of doing so.

  1. .h files act as a reference point for anyone to use the classes/functions/ and other data structures and APIs you've implemented in your code. Anyone unaware of the class structure will refer the .h first.
  2. You can distribute a library revealing only the .h file without revealing your actual implementation. Usually they come up with external APIs (again in .h files) which are the only entry points to any code within the library and can be used by 3rd parties if they wish to share the code.
  3. If you include a .c or .cpp file in multiple places - you'll not see any errors during the compilation - but the linker will bail out complaining about duplicate symbols. Since it has more than one copy of all those functions/methods part of the .c/.cpp file you included.

Exceptions

  1. Inline function implementations need to be present in .h files to be effective. There are cases when the compiler might automatically be able to decide that a piece of code can be inlined - but in some cases it requires the presence of the inline keyword. NOTE: I'm only talking about the latter here. The compiler will inline any function only if it sees the inline keyword. In other words if a .cpp has the following piece of code:

    class A; A.my_inline_method();

If my_inline_method() is not visible to the compiler as an inline function when compiling this cpp file, it will not inline this function.

  1. Templates are similar to inline methods when it comes to compilation - when the code for a template needs to be generated by the compiler in the .cpp where it is used - it needs to know the entire implementation of that template. Since template code generation is compile-time and NOT runtime.

I've mentioned the more common philosophies behind this. Feel free to edit this answer to add more if I've missed.

More info on template stuff here: Why can templates only be implemented in the header file?

EDIT: Made changes based on @Forever's comment to avoid ambiguity.

Community
  • 1
  • 1
Tuxdude
  • 47,485
  • 15
  • 109
  • 110
  • Inline function implementations need to be present in .h files otherwise they'll not be inlined everywhere. The compiler will inline any function only if it sees the inline keyword. In other words if a .cpp has the following piece of code: No... inline keyword in only recomendation to compiler + functions may be inlined while linkage. – ForEveR Jul 19 '12 at 21:16
  • What would you typically expect in a case like mine then? Included `.cpp` files, or an alternate extension such as `.ipp` or `.impl` as others have suggested? – Gordon Bailey Jul 19 '12 at 21:31
  • Check out this link about possible problem of having template implementations in .cpp files: http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file If you think you wont be running into this scenario - just keep your current implementation, if not refactor it. – Tuxdude Jul 19 '12 at 21:35
  • Thanks for that link, it seems to confirm what I'm seeing here. – Gordon Bailey Jul 20 '12 at 16:03
1

I'm answering my own question to add that a somewhat standard extension for template implementation seems to be .tcc. It's recognized by github's syntax highlighter, and is also mentioned in the gcc man page:

C++ source files conventionally use one of the suffixes .C, .cc, .cpp, .CPP, .c++, .cp, or .cxx; C++ header files often use .hh, .hpp, .H, or (for shared template code) .tcc;

If I'm misunderstanding the intended use of the .tcc extension, please let me know and I will delete this answer!

Gordon Bailey
  • 3,881
  • 20
  • 28
  • Thanks for this answer; it gives alternatives to `.ipp` or `.impl`, which in my case don't exactly fit a project that uses `.cc` for source files. – congusbongus Mar 06 '13 at 23:35