-2

I have this header file:

Utility.h:

#pragma once

#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <Windows.h>

using namespace std;

template<std::size_t> struct int_ {};

template <class Tuple, size_t Pos> 
std::ostream& print_tuple(std::ostream& out, const Tuple& t, int_<Pos>);

struct Timer {
public:
    Timer();
    void start();
    double getMilliSec();
private:
    LARGE_INTEGER frequency;        // ticks per second
    LARGE_INTEGER t1, t2;           // ticks
};

//...

#include "Utility.cpp"

And this implementation file:

Utility.cpp:

#include "Utility.h"
template <class Tuple, size_t Pos>
std::ostream& print_tuple(std::ostream& out, const Tuple& t, int_<Pos>) {
     ...
}

Timer::Timer() {
    // get ticks per second
    QueryPerformanceFrequency(&frequency);
}

void Timer::start() {
    QueryPerformanceCounter(&t1);
}

double Timer::getMilliSec() {
    QueryPerformanceCounter(&t2);
    return (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
}

Which returns this error:

error C2995: 'std::ostream &print_tuple(std::ostream &,const Tuple &,int_<Pos>)': function template has already been defined
error C2084: function 'Timer::Timer(void)' already has a body
...

The problem is not about guards (as suggested in this question) since I use #pragma once

I`ve read about of implementing .tpp files for template class implementation, but I find it an horrible solution, since Visual Studio will format nothing from this file.

trying to define Utility.tpp: (WRONG SOLUTION)

So I substituted #include "Utility.cpp with #include "Utility.tpp in Utility.h and define...

Utility.tpp

Timer::Timer() {
    // get ticks per second
    QueryPerformanceFrequency(&frequency);
}

void Timer::start() {
    QueryPerformanceCounter(&t1);
}

double Timer::getMilliSec() {
    QueryPerformanceCounter(&t2);
    return (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
}

And now the error returned is:

1>Memoization.obj : error LNK2005: "public: __cdecl Timer::Timer(void)" (??0Timer@@QEAA@XZ) already defined in HelloWorld.obj
...

This is the main btw:

HelloWorld.cpp:

#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//#include "Memoization.cpp"
#include<vector>
#include"Utility.h"

using namespace std;

int main()
{
}

trying to define Utility.tpp: (RIGHT SOLUTION, FINALLY)

As in the comment made me notice, as an idiot I imported the Time methods in the .tpp file, and obviously I should have imported the templates function, and so in Utility.tpp contains print_tuple while Utility.cpp contains the 3 Timer functions.

Community
  • 1
  • 1
justHelloWorld
  • 6,478
  • 8
  • 58
  • 138
  • What is `#include "Utility.cpp"` doing in the header file? – NathanOliver May 02 '16 at 12:57
  • [Here](http://www.codeproject.com/Articles/48575/How-to-define-a-template-class-in-a-h-file-and-imp) method 3 or [here](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) "a common solution..." – justHelloWorld May 02 '16 at 12:59
  • 1
    Well, yes, "a common solution", but a solution to a problem that this code **does not have**. There are no templates here. – Pete Becker May 02 '16 at 13:05
  • Look at the updated answer ;) – justHelloWorld May 02 '16 at 13:09
  • Why do you want to implement the template function in a cpp file, when you are including the cpp file in the header anyway, it will act as a header file, but only obfuscate things. I really do not like this approach. – Tommy Andersen May 02 '16 at 13:11
  • You've gotten valid answers and comments about your original code, and now you've edited your question to pretend that it was about something else. I, for one, have no interest in playing that game. – Pete Becker May 02 '16 at 13:12
  • For God's sake, I have said "updated answer" for a reason. And now I realize that's "answer" and not "question", I'll have to edit that too :D What happened here happened many times to me, nobody ever complained (guess what: you can copy and paste the wrong function) – justHelloWorld May 02 '16 at 13:15
  • If someone feels confused because of the answer below, the "change log" exists for a reason ;) – justHelloWorld May 02 '16 at 13:16
  • @TommyA I've often seen this pattern to prune the public header from template definitions, but the implementation file has a particular extension such as .tpp or .inl. – Quentin May 02 '16 at 13:17
  • @Quentin but (as I wrote at the end of my question) I consider that an horrible solution since you loose all the IDE advantage if you're gonna write a `.tpp` file – justHelloWorld May 02 '16 at 13:18
  • @Quentin yes and choosing a different extension has the upside of making it obvious (or at least more obvious) to the reader that the file is not a standard source unit, but an implementation file. Using .cpp will make the file prone to being picked up by the compiler more easily. – Tommy Andersen May 02 '16 at 13:18
  • 1
    @justHelloWorld ... fix your IDE ? – Quentin May 02 '16 at 13:20
  • I agree with @Quentin using a less than optimal IDE is no excuse for introducing hacks like this. :) – Tommy Andersen May 02 '16 at 13:21
  • **.tpp** section added – justHelloWorld May 02 '16 at 13:29
  • @justHelloWorld Now your problem appears to be mixing template implementations and non-template implementations. Another reason why I don't like moving the template implementation outside of the header. The class Timer, is not a template, and is thus defined in every source unit that include the header. That means that you will have multiple object files having the same implementation. – Tommy Andersen May 02 '16 at 13:40
  • Thanks, like an idiot I imported the `Time` methods in the `.tpp` file, while I should have imported `operator<<` instead. Now it works. You gained the best answer @TommA , thanks! – justHelloWorld May 02 '16 at 13:59

3 Answers3

3

If you are going to include a cpp file into a header file then you need to exclude that cpp file from compiling in the project. If you do not then the header file will have what the cpp file has and when the compiler compiles the cpp file into an object you will have two copies of the of the definitions. One in the header file as it has a copy of the cpp file in it and one in the cpp file as that is what is actually compiled. This leads to the redefinition errors.

Once you remove Utility.cpp from being compiled then any other cpp file that includes Utility.h will have a copy the full source since Utility.cpp is also included.

To remove Utility.cpp from compiling see: How to exclude files from Visual Studio compile?


If the only reason you are using a cpp file is because tpp files do not format C++ code as C++ then you can just configure MSVS to treat tpp files as C++ files. If you go to Tools -> Options -> Text Editor -> File Extensions you can add a file extension to the formatting. Enter the extension in the extension box, select Microsoft Visual C++ from the editor drop down and then click add.

Now you can use a tpp file instead of a cpp file and you do not have to remember to exclude the cpp file from the build. You also get to conform to modern practices.

Community
  • 1
  • 1
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
0

There are main two problems:

  • You have placed intended header code in a ".cpp" file, which your IDE by default will treat as a main source code file (translation unit).

  • You are including non-inline function definitions (the class member functions) in the global namespace in a header. When that header is included in two or more translation units you will get a One Definition Rule (ODR) violation. In practice the linker will complain.

To fix this:

  • Change the filename extension from ".cpp" to e.g. ".hpp" or just plain ".h". It is code intended for header file use. The filename extension should reflect that, instead of misleading.

  • Declare the functions inline, or place definitions within the class definition.


In other news, possibly one of the <chrono> clocks, from the standard library, will serve your purpose so that you don't have to include <windows.h> in a header. It does drag in a zillion unreasonable macros. Including, by default, lowercase min and max macros, so this code is very ungood as given.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
-1

Remove the #include "Utility.cpp" line from Utility.h. Then compile the Utility.cpp again

dutchdukes
  • 385
  • 2
  • 9