0
/*--------------------utilities.h-------------------------------------*/

#ifndef UTILITIES_H
#define UTILITIES_H

template<class T> int compare(const T&,const T&);

#include<utilities.cpp>
#endif

/*--------------------utilities.cpp-------------------------------------*/

template<class T> int compare(const T &v1 , const T &v2)
{
    if (v1 < v2) return -1;
    if (v2 < v1) return 1;
    return 0;
}

/*--------------------main.cpp------------------------------------------*/

#include<iostream>
#include<utilities.h>
using namespace std;

int main(int argc , char *argv[])
{
    cout << compare(1,2) << endl;

    return 0;
}

The code above is an example from a book. However, it gives errors when I compile the three files:

utilities.h:6:24: fatal error: utilities.cpp: No such file or directory
compilation terminated.
main.cpp:2:22: fatal error: utilities.h: No such file or directory
compilation terminated.

I don't know why I get "No such file or directory"!

Shahbaz
  • 46,337
  • 19
  • 116
  • 182
std
  • 873
  • 2
  • 10
  • 17
  • You need to put the template definition in the header file? http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – madu Sep 05 '12 at 09:28
  • @madu no. .cpp file includes in .hpp. all is okay here. – ForEveR Sep 05 '12 at 09:29
  • The error lies in the fact that the compiler fails to find the files to include, but to help more you should give compiler name and command invoked for compilation. – CharlesB Sep 05 '12 at 09:29
  • @ForEveR Thank you. I thought template headers need to be where they are declared. – madu Sep 05 '12 at 09:30
  • 1
    How are you compiling them? (which compiler and which command are you using to compile) – SingerOfTheFall Sep 05 '12 at 09:33

4 Answers4

2

Problem 1

When you write:

#include <utilities.h>

The compiler looks for utilities.h in it's default include paths or ones that are specified explicitly (e.g. in g++ with -I).

You can write:

#include "utilities.h"

to make it first look at a path relative to the source file.

Problem 2

You have included utilities.cpp in the header file (also with the same problem as above). This is not recommended, but not strictly wrong. However, in that case, the contents of that file already get compiled and included in the main.o, so you actually don't need to compile and link the two object files, but only main.cpp suffices.

The recommended approach to writing templates is to write everything in the header file (I know, it's not nice):

/*--------------------utilities.h-------------------------------------*/

#ifndef UTILITIES_H
#define UTILITIES_H

template<class T>
static inline int compare(const T &v1, const T &v2);
{
    if (v1 < v2) return -1;
    if (v2 < v1) return 1;
    return 0;
}

#endif

/*--------------------main.cpp------------------------------------------*/

#include <iostream>
#include "utilities.h"

using namespace std;

int main(int argc , char *argv[])
{
    cout << compare(1,2) << endl;

    return 0;
}

You simply compile main.cpp.

Shahbaz
  • 46,337
  • 19
  • 116
  • 182
  • approach 2 should never compile on most compilers. – ForEveR Sep 05 '12 at 09:47
  • @forever, yeah, I thought I saw somewhere they did that. – Shahbaz Sep 05 '12 at 09:49
  • @Shahbaz The recommended approach to writing templates _is_ to put the implementation in a separate file, which is included from the header, as he has done. The only difference would be that this file should probably not end with `.cpp`, since most people would automatically compile anything ending with `.cpp`. – James Kanze Sep 05 '12 at 11:14
  • @JamesKanze, so what extension would you give to that other file? – Shahbaz Sep 05 '12 at 11:31
  • @Shahbaz In my own code, I use `.cc` and `.hh` for the normal sources and headers, and `.tcc` for the template implementations. For someone using `.cpp` and `.hpp`, I would suggest something like `.tpp`, but it really doesn't matter, as long as you're consistent (and that it isn't something which would be recognized as a file to compile: not `.cpp`, `.cxx` or `.cc`.) – James Kanze Sep 05 '12 at 12:38
1

The book isn't giving you the contents of one file, it's giving you the contents of several. When the listing says

/*--------------------utilities.cpp-------------------------------------*/

the authors mean "Put the following code in the file `utilities.cpp". It looks like you haven't got that file. Do that, and it will all compile.

hcarver
  • 7,126
  • 4
  • 41
  • 67
  • If you look closely at the error messages, you will see that the OP has at least `utilities.h` and `main.cpp`, hence I believe it's not the case. – SingerOfTheFall Sep 05 '12 at 09:32
  • That error message tells us that OP doesn't have `utilities.cpp`. – hcarver Sep 05 '12 at 09:33
  • yes, but it says `utilities.h:6:24:` which means that the error happens inside `utilities.h`, so the OP didn't put the whole example into one file as you suggested. – SingerOfTheFall Sep 05 '12 at 09:34
  • @Hbcdev The error message tells us that compiler couldn't find the files, not that they don't exist. The most likely reason why the compiler couldn't find them is because the OP told it not to look in the current directory, by using the `<...>` form of `#include`, rather than the `"..."` form. – James Kanze Sep 05 '12 at 09:36
  • @JamesKanze Disagree. That behaviour is implementation-specific and OP's compiler is finding `` just fine (assuming OP has copied the error output verbatim). – hcarver Sep 05 '12 at 09:40
  • @Hbcdev Whether you agree or not is irrelevant. All compilers do more or less the same thing: for `"..."`, search in the directory where the including file is found, then proceed as for `<...>`. for `<...>`, search in the directories specified as options in the command line, then in a number of system specific places where the standard library and the system headers will be found. And I don't see how "fatal error: utilities.h: No such file or directory compilation terminated" can be taken to mean that the compiler is finding `` just fine. – James Kanze Sep 05 '12 at 11:05
  • Like I said, I thought OP had copied error output verbatim, and had interpreted the error as being reported for main.cpp via utilities.h. Didn't even occur to me that OP would be compiling utilities.h directly. – hcarver Sep 05 '12 at 11:25
1

Change

#include<utilities.cpp>

to

#include "utilities.cpp"

and

#include<utilities.h>

to

#include "utilities.h"

Inclusion with <> is meant for "system" headers. I'd also suggest that you rename utilities.cpp to utilities.ipp, to differentiates source files that are included from those that are compiled directly.

Nicola Musatti
  • 17,834
  • 2
  • 46
  • 55
1

Whether it was in a book or not, there's an error in the code. It should be

#include "utilities.cpp"

and

#include "utilities.h"

Normally, when you use the <...> form of the include, the compiler will not look for the file in the current directory. (You can usually tell it to do so, with an option along the lines of /I. or -I., but using the correct form of the include is preferable.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329