1

I am trying to access one header file in multiple C++ files. The header file is defined as follows:

#ifndef UTILS
#define UTILS

void toUpper(string &str) {
    for(unsigned int i=0; i<str.length(); i++) {
            str.at(i) = toupper(str.at(i));
    }
}

void toLower(string &str) {
    for(unsigned int i=0; i<str.length(); i++) {
            str.at(i) = tolower(str.at(i));
    }
}


#endif // UTILS

When I compile the code I get the following error: enter image description here

As far as I know, this should not return multiple definitions since I am restricting the code from being defined more than once. I also tried using the precompiled directive "#pragma once"

jxh
  • 69,070
  • 8
  • 110
  • 193
  • 1
    Please provide the code(at least some amount of it) that you have omitted. Without it there is no way for us to help you. – Jason Oct 16 '21 at 05:42
  • @AnoopRana I have added code – InputBlackBoxOutput Oct 16 '21 at 05:45
  • 1
    The include guard you use prevents some forms of multiple-definition errors but not all. It prevents more than one copy of `Utils.hpp` from appearing in the same translation unit. However, it's still a violation of the one definition rule for more than one copy of `Utils.hpp` to appear across multiple different translation units, and the include guard does nothing to prevent that. (Indeed, you don't _want_ to prevent that, since your goal is to use these functions in multiple source files.) The remedy for this is, as answered below, the `inline` keyword. – Nathan Pierson Oct 16 '21 at 05:48
  • 1
    Mistakes in the content of header files cause the problem. Cleaning that up solves it. That matfches the 2nd option in the answer here, Not defining code twice is the key. Neither reinclusion guard nor pragma once prevent it. Using inline solves/hides the problem, but is not the only solution. I disagree that my dupe proposal is not applicable. @jxh – Yunnosch Oct 16 '21 at 06:02
  • @Yunnosch In this case, it is more relevant to explain how to properly define inlined functions, rather than suggest to the user to never use them. – jxh Oct 16 '21 at 06:06

1 Answers1

6

There are 2 solutions to this problem.

Solution 1

You can add the keyword inline infront of the function like:

myfile.h

#ifndef UTILS
#define UTILS

inline void toUpper(string &str) {
    for(unsigned int i=0; i<str.length(); i++) {
            str.at(i) = toupper(str.at(i));
    }
}

inline void toLower(string &str) {
    for(unsigned int i=0; i<str.length(); i++) {
            str.at(i) = tolower(str.at(i));
    }
}


#endif // UTILS

Now you can include this header in different files without getting the mentioned error.

Solution 2

You can create a separate .cpp file and put the definition there. This would look like:

myfile.h

#ifndef UTILS
#define UTILS

//just declarations here
void toUpper(string &str);    //note no inline keyword needed here

void toLower(string &str);    //note no inline keyword needed here

#endif // UTILS

myfile.cpp

#include "myheader.h"
void toUpper(string &str) {
    for(unsigned int i=0; i<str.length(); i++) {
            str.at(i) = toupper(str.at(i));
    }
}

void toLower(string &str) {
    for(unsigned int i=0; i<str.length(); i++) {
            str.at(i) = tolower(str.at(i));
    }
}


Jason
  • 36,170
  • 5
  • 26
  • 60