7

I ran into a behavior today that I don't completely understand. I jump right into a minimal code example and will explain along the way.

I have 2 Projects: A static c++ library and a console application.

Static Lib Project:

Library.h

#pragma once

namespace foo
{
    int testFunc();

    class StaticLibClass
    {
    public:
        static int testMemberFunc();
    };

}

Library.cpp

#include "Library.h"

using namespace foo;

// just some functions that don't do much
int testFunc()
{
    return 10;
}

int StaticLibClass::testMemberFunc()
{
    return 11;
}

Console Application Project:

main.cpp

#include "library.h"

using namespace foo;

void main()
{
    // calling this function reslts in LNK2019: unresolved external symbol...
    testFunc();

    // this function works just fine
    StaticLibClass::testMemberFunc();
}

As you can see the static member function of a class works just fine. The single testFunc however results in a linker error. Why is this?

The solution to the problem is to not use "using" in the Library.cpp file but also wrap it in the namespace like so:

Changes that fix the problem:

Library.cpp

#include "Library.h"

namespace foo
{

    // just some functions that don't do much
    int testFunc()
    {
        return 10;
    }

    int StaticLibClass::testMemberFunc()
    {
        return 11;
    }
}
derkie
  • 85
  • 1
  • 5
  • 3
    You have a declaration for foo::testFunc() but a definition for ::testFunc(). The linker complains because it cannot find foo::testFunc() – Hans Passant Jul 13 '14 at 20:49
  • @πάντα ῥεῖ It is somewhat a duplicate but they don't really talk about namespaces in that question thread. I personally wouldn't have found the cause of my problem from reading the thread you linked. – derkie Jul 13 '14 at 21:07
  • @Hans How come the StaticLibClass is in the namespace then? And if I do the implementation in the console application the "using namespace" is enough for the compiler to know which function I'm implementing. – derkie Jul 13 '14 at 21:08
  • @derkie `using namespace X;` means that when you are doing *name lookup* -- i.e. looking to see where a name was declared -- then `X` is searched. However when you are declaring (or defining) a function, there is no name lookup. Your last question is like asking : `using namespace std; int k;` - why didn't this declare `std::k` ? – M.M Jul 13 '14 at 22:21
  • I see, so the reason the class works is because i declare the class in the header file inside of the namespace block. But when using plain functions that don't belong to a class already you have to explicitly define the namespace. So I guess classes and namespaces are kinda similar in that manner, when implementing a class member function you always have to add the class "void ClassName::function()". Thanks for the answers. – derkie Jul 13 '14 at 22:44
  • @πάνταῥεῖ: please stop downvoting and close voting everything has the expression "unresolved external symbol" with that clearly bad "canonical duplicate". This is not constructive.. Even if it manages to get closed, I will instantly reopen it with the binding reopen vote. – László Papp Jul 14 '14 at 03:45
  • [This answer](http://stackoverflow.com/a/12574403/819272) provided by @πάνταῥεῖ has the cause (first of three bullets: "Function/variable declared in one namespace, defined in another"), same as explained by Hans Passant – TemplateRex Jul 14 '14 at 07:55
  • @FinalContest you should read the linked answer, my comment above and Hans Passants comment. It *is* a duplicate. – TemplateRex Jul 14 '14 at 07:56
  • 1
    Thank you TemplateRex, you're right. I must have missed that one bullet point before since I didn't completely understand that defining a function while 'using namespace' doesn't define it in that same namespace. So there was a fundamental misunderstanding about namespaces on my part which doesn't really relate to the whole 'unresolved external' problem. – derkie Jul 14 '14 at 08:23
  • @TemplateRex: read and reopened accordingly. We need precise and concise answers, not a lot of reading for a very simple issue that may be there in the Xth paragraph of the Yth answer. This is time-consuming. Furthermore, duplicates are for questions, not answers. On a side note, +1 to the question and answer. – László Papp Jul 14 '14 at 08:53

1 Answers1

5

You either need to wrap the body of the implementation functions/methods in a namespace statement that matches the original header, or you can use fully qualified names which is probably better C++ style:

#include "Library.h"

// just some functions that don't do much
int foo::testFunc()
{
    return 10;
}

int foo::StaticLibClass::testMemberFunc()
{
    return 11;
}

You don't need a using namespace foo; in this version. You are already in the namespace 'foo' when implementing the body's of those two methods, but it can be convenient depending on other types in that namespace.

Chuck Walbourn
  • 38,259
  • 2
  • 58
  • 81