Gunnar
Gunnar

Reputation: 986

LNK2005: already defined error

I am working on a school assignment, and I get this strange error (I am quite new to C++).

I should find the first value between 1500 and 1900. When I build it the first time, everything is ok, but when I build it the next time, I get this error:

error LNK2005: "bool __cdecl greaterThan1500SmallerThan1900(int)" (?greaterThan1500SmallerThan1900@@YA_NH@Z) already defined in Lab5.obj

If I then change the code slightly (change the type in the predicate function to double) it builds again one time.

template<typename T>
T MyStlClass<T>::myFindIf(list<T> &theList) {

    list<T>::iterator it = find_if(theList.begin(), theList.end(), greaterThan1500SmallerThan1900);
    return *it;
}

bool greaterThan1500SmallerThan1900(int value){
    return (value >= 1500 && value <= 1900);
}

I have read on this site that it is because that I include the ".cpp" file, but on the other hand, I have also read, that I need to include the ".cpp" file, when I am using templates.

Upvotes: 0

Views: 661

Answers (3)

Mr.C64
Mr.C64

Reputation: 43024

If you are writing an header-only library/module, then use #pragma once to avoid multiple inclusions, and mark the greaterThan1500SmallerThan1900 function inline:

// MyStlClass.hpp

#prgma once

....

template<typename T>
T MyStlClass<T>::myFindIf(list<T> &theList) {

    list<T>::iterator it = find_if(theList.begin(), theList.end(), greaterThan1500SmallerThan1900);
    return *it;
}

// NOTE inline here:
inline bool greaterThan1500SmallerThan1900(int value){
    return (value >= 1500 && value <= 1900);
}

Upvotes: 0

Anton Kovalenko
Anton Kovalenko

Reputation: 21517

Your greaterThan1500SmallerThan1900 is not a template, that's why it's wrong to #include its body multiple times (and that's why it must be linked exactly once).

You have to split out this function from the templated stuff. This function should be in a cpp file never #included by anything, but added to your project. (It seems that you already have its declaration where it's called -- it should remain so).

As of the templates, you may heed another answer's advice (renaming to *.ipp which you will #include, removing from project), but the error will disappear before you do (compiling additional template-only source file to an empty object is useless, but it does not hurt).

Upvotes: 0

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385395

I have also read, that I need to include the ".cpp" file, when I am using templates.

Throw away/downvote/identify for us the resource that told you to do that.

There is a good reason that it did so, but the recommendation was wrong and it has led you directly to this issue.

Never #include a .cpp.

The file you put template definitions in should be called something like .ipp rather than .cpp, so that then your IDE does not confuse it with a "regular" source file and build it with the rest of your project. Such a file is then, like a .h, only #included.

Upvotes: 1

Related Questions