0

i have a relatively small c++ project and i decided to make a Utils header file which would just contain some small helper functions etc. It was all working fine when i was declaring functions that were using a template, then i tried to make a function which didnt need a template, and suddently it doesn't work.

The result i get is a linker error; already defined in (file).obj

I cannot even declare a simple void function, everything without template gives a linker error.

I have NO IDEA whatsoever what could be causing this. Here is the code for the header file... Thanks in advance.

#pragma once

namespace Utils
{
    std::string GetActiveWindowTitle()
    {
        // This doesnt work either, also gives linker error.
        return active_window;
    }

    template<typename T>
    void Print(char * value, T printValue)
    {
        std::cout << value << ": " << printValue << std::endl;
    }

    template<typename T>
    void Print(T printValue)
    {
        std::cout << "DEBUG: " << printValue << std::endl;
    }

    void PrintStr(std::string str)
    {
        // This doesn't work because it doesnt have the template, it gives a linker error
        std::cout << "DEBUG: " << str.c_str() << std::endl;
    }
}
Skosh
  • 165
  • 1
  • 9
  • 8
    Add `inline` to the function definitions in your header, or else move the function definitions to a separate translation unit (.cpp file). You don't need the `inline` specifier for *function-templates* – WhiZTiM Sep 17 '17 at 09:45
  • 7
    Tip: templates are implicitly `inline`. – Rakete1111 Sep 17 '17 at 09:45

2 Answers2

2

A function-template is implicitly inline. Thus, when defined in a header file, it doesn't violate ODR (One Definition Rule). For non-template functions in header files, you should either define them as inline, or define them in a separate translation unit.

So, you could do:

#pragma once

namespace Utils
{
    inline std::string GetActiveWindowTitle()
    {
        return active_window;
    }

    template<typename T>
    void Print(char * value, T printValue)
    {
        std::cout << value << ": " << printValue << std::endl;
    }

    template<typename T>
    void Print(T printValue)
    {
        std::cout << "DEBUG: " << printValue << std::endl;
    }

    inline void PrintStr(std::string str)
    {
        std::cout << "DEBUG: " << str.c_str() << std::endl;
    }
}

See Inline keyword vs header definition

WhiZTiM
  • 21,207
  • 4
  • 43
  • 68
-2

If you include your header to more than one cpp, the function will be defined more than once and the linker will give you the error described above. See What is the difference between a definition and a declaration? or What are forward declarations in C++?

Marc
  • 69
  • 6
  • 1
    Right now this answer is of a low quality. If you believe that there is another answer, which answer this question, flag question as duplicate (or vote to close, when you have enough reputation), don't answer it. And if it no a duplicate, provide all information needed to solve problem inside your answer. Right now this answer does not tells how to __solve__ problem, it merely hints at the reason, sending reader to look through other questions to find more info there. – Revolver_Ocelot Sep 17 '17 at 10:03