So for some reason I have experienced the behavior that adding a namespace to my .h and .cpp files for a set of functions breaks my linker. I'm using Visual Studio 2012. Here's my scenario (simplified)
functions.h
int functionA();
int functionB();
functions.cpp
#include "functions.h"
int functionA() { return 0; }//we could pretend there's actual code here
int functionB() { return 0; }//we could pretend there's actual code here
and the actual useage of it is in some cpp file thusly:
pointers.h
#include "functions.h"
class GetPointers
{
public:
typedef int (*FunctionPointer)(void);
static FunctionPointer funcPointerA() { return &functionA; }
static FunctionPointer funcPointerB() { return &functionB; }
};
Well that's all fine and dandy. I can call the static method of GetPointers and get a function pointer which works. Everythings been tested and everything is happy. Now I thought I would simply add some namespaces to make sure I don't have any problems again in the future. So I simply modify the three code files to use namespaces. What happens is a link error which refers to the function funcPointerA() and funcPointerB() of the GetPointers class, with the full namespace name to functionA and functionB.
functions.h
namespace fun {
int functionA();
int functionB();
}
functions.cpp
#include "functions.h"
using namespace fun;
int functionA() { return 0; }//we could pretend there's actual code here
int functionB() { return 0; }//we could pretend there's actual code here
and the actual useage of it is in some cpp file thusly:
pointers.h
#include "functions.h"
namespace fun {
class GetPointers
{
public:
typedef int (*FunctionPointer)(void);
static FunctionPointer funcPointerA() { return &functionA; }
static FunctionPointer funcPointerB() { return &functionB; }
};
}
I don't get a build error, only a link error about fun::functionA and fun::functionB. Is there something implicitly wrong with using function pointers from namespaces?
The problem is that your definitions:
int functionA() { return 0; }
int functionB() { return 0; }
are in the global namespace; so they declare new functions there rather than define the functions declared in namespace fun.
The best fix is to qualify the names in the definitions:
int fun::functionA() { return 0; }
int fun::functionB() { return 0; }
This is preferable to putting the definitions inside the namespace, since it gives a compile-time check that the functions match their declarations.
Related
I'm trying to run some test code to learn c++, but I am getting an error telling me the reverseDigits function was not declared in the main.cpp scope:
error: 'reverseDigits' was not declared in this scope.
But the #include "Solutions.h" header was included in main.cpp, so I thought that it would be in scope.
I have checkout other questions, but the answers all relate to problems with circular header file inclusion, which I don't think is the problem here.
Do you know why I am seeing that error?
Solution.h
#ifndef SOLUTION_H
#define SOLUTION_H
class Solution {
public:
Solution();
~Solution();
int reverseDigits(int x);
};
#endif // SOLUTION_H
Solution.cpp
#include "Solution.h"
#include <string>
Solution::Solution()
{
}
Solution::~Solution()
{
}
int Solution::reverseDigits(int x) {
std::string num_string = std::to_string(x);
std::string reversed_num_string {};
for (int i = num_string.length() - 1; i > 0; i--) {
reversed_num_string.push_back(num_string[i]);
}
return stoi(reversed_num_string);
}
main.cpp
#include <iostream>
#include "Solution.h"
int main()
{
int x {123};
int result = reverseDigits(x);
std::cout << result << std::endl;
return 0;
}
You declared reverseDigits as a member function of the Solution class, then defined it without qualifying it as a member of Solution (Edit: You've since changed it to match declaration and definition, but at point of use, you're trying to use an unqualified function, not a member of a Solution object). The declaration in the .h file is visible, but the definition in the .cpp is unrelated, and not visible to main.cpp.
Declare the function outside the class (since it's clearly unrelated to the class), and it should work, changing to:
class Solution {
public:
Solution();
~Solution();
};
int reverseDigits(int x); // NOT inside the class definition
I'll note: I have no idea why you have a Solution class at all. Defining reverseDigits doesn't require it, so I'm not seeing the point. If this is part of some automated evaluation framework, you'll have to give more details
Along with ShadowRanger's valid suggestion, I'll highlight upon how you could have used the data as part of your Solution class and applied the function on it.
Refactoring your class to
class Solution {
public:
Solution(int data);
~Solution();
int reverseDigits();
private:
int m_data;
};
Solution::Solution(int data)
{
m_data = data;
}
Solution::~Solution()
{
}
Even though you could have used std::reverse, fixing the error on the i>=0 is needed to have your own reverse function
int Solution::reverseDigits() {
std::string num_string = std::to_string(m_data);
std::string reversed_num_string {};
for (int i = num_string.length() - 1; i >= 0; i--) {
reversed_num_string.push_back(num_string[i]);
}
return stoi(reversed_num_string);
}
Now call it from your main() as
int main() {
int x = 123;
Solution sol(x);
std::cout << sol.reverseDigits() << std::endl;
return 0;
}
I am writing a namespace that requires certain functions inside to have access to a particular variable (also declared within the namespace). Normally when I do this, I have the variable declared in the .cpp file to prevent outside access to it.
.h
namespace Example
{
int myFunc();
}
.cpp
namespace Example
{
int hiddenVar;
int myFunc()
{
.. do something with hiddenVar
return someValue;
}
}
My problem is that I need to define a template function that requires access to this hidden variable. Unfortunately since the body of the template function must be defined in the header file it wont have access to the variable hidden in the .cpp.
.h
namespace Example
{
template< typename T >
void myFunc( const T& myT )
{
.. do something with hiddenVar // doesnt know what hiddenVar is
}
}
.cpp
namespace Example
{
int hiddenVar;
}
Is there anyway to have a variable hidden within a namespace while giving a template function in the header access to it?
.h:
namespace Example
{
int * get_hiddenVar();
template< typename T >
void myFunc( const T& myT )
{
int * hiddenVarPtr = get_hiddenVar();
.. do something with *hiddenVarPtr
}
}
.cpp
namespace Example
{
int hiddenVar=0;
int * get_hiddenVar()
{
return &hiddenVar;
}
}
You cannot do this directly, but you can use a function. Since hiddenVar does not depend on the template parameters, you can do this:
.h
namespace Example
{
void Function(); // Use the right function prototype here, of course,
// as long as it does not depend on T
template<typename T>
void myFunc(const T& myT)
{
//...
Function();
//...
}
}
.cpp
namespace Example
{
int hiddenVar;
void Function()
{
// Do something with hiddenVar
}
}
If your use of hiddenVar depends on T, of course, you are out of luck.
Put it in a nested namespace called 'Details' and stop worrying.
'Hiding' a variable using namespaces and private etc are not security-constructs, but there to facilitate better code.
While attempting to make a function object wrapper class for raw functions, I'm encountering a multiple definition error by trying to define in a namespace in a header file and declare it in the source. This works fine but when I try to instantiate a function object based on the raw function in the namespace, I get the error.
space.h
#ifndef SPACE_H
#define SPACE_H
namespace fobj{
class function_object
{
public:
function_object(double (*f)(double)) { raw_function = f; }
double operator()(double x) {return raw_function(x); }
private:
double (*raw_function)(double);
};
}
namespace fraw {
double raw(double x);
/** below is the trouble maker. When removed, the error doesn't occur. But also,
when the above is instead declared inline, the error doesn't occur either. **/
fobj:: function_object obj( raw );
}
#endif
space.cpp
#include "space.h"
double fraw:: raw(double x) { return x; }
main.cpp
#include <iostream>
#include "space.h"
int main()
{
std::cout<< fraw::raw(1.5)<<std::endl;
std::cout<< fraw::obj(2.5)<<std::endl;
return 0;
}
fobj:: function_object obj( raw ); is a definition - including the header in multiple translation units breaks the one definition rule. Declare the variable as extern and define it in a single implementation file.
that this snippet of code actually do?
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
void test();
namespace {
static struct StaticStruct {
StaticStruct() {
test();
}
} TheStaticSupport;
}
int main(void) {
return 0;
}
void test() {
printf("testing function\n");
}
why does the test function actually get called? and why use the "anonymous" namespace? I found this piece of code in an open source project...
This:
static struct StaticStruct {
StaticStruct() {
test();
}
} TheStaticSupport;
Is equivalent to this:
struct StaticStruct {
StaticStruct() {
test();
}
};
static StaticStruct TheStaticSupport;
It defines a type named StaticStruct and an instance of the type named TheStaticSupport with internal linkage (though, since it is declared in an unnamed namespace, the static is redundant).
The constructor for TheStaticSupport is called before main() is entered, to construct the object. This calls the test() function.
The anonymous namespace gives the contained objects internal linkage, as their fully qualified name can never be known to anyone outside the translation unit. It's the sophisticated man's version of the old static in C.
Note that you do declare a global object of type StaticStruct, and its constructor (which runs before main() is called) calls test().
Is it legal to define the implementation of a function or class members outside the unnamed (anonymous) namespace they've been defined inside.
My compiler accepts it but I want to be sure it's legal
e.g.
////////////////
// foo.cpp
namespace {
struct X
{
void foo(int x);
};
}
// Is this legal?
void X::foo(int x)
{
}
The reason is I would like to avoid the unnecessary indentation imposed by our uncrustify formatting
It is really no different than the following, which is totally legit:
namespace ns {
struct s {
void f();
};
}
using namespace ns;
void s::f() { }
The names from the named namespace are brought into the global namespace and thus definitions can be provided for them there. The only difference with the unnamed namespace is that it has no name (really, it has some unique, unutterable name) and the using namespace is implicit.
#include <iostream>
using namespace std;
namespace
{
struct X
{
X(int);
int x_;
};
}
X::X(int x) : x_(x) {}
int main()
{
X x(5);
cout << x.x_ << "\n";
return 0;
}
Compiles (and runs) under gcc 4.6.0
Yes. It's perfectly legal. The difference an unnamed namespace makes is that, the content of the namespace is available only within the file it's declared. If it's in .h file then, it will be added to all the subsequent .cpp file and every .cpp file will have a unique copy of the contents of the namespace.
In fact it's a better way to declare a global static variable. Now see, what kind of difference it will make:
namespace {
struct X
{
void foo(int x);
};
int i; // declare this global variable
}
If you put this code inside a header file then, wherever that header file is #includeed, all those .cpp file will have a different copy of int i; inside them. Changing the value of i in one .cpp file doesn't affect the other .cpp file.
Moreover, it will not give linker error for multiple definitions, since it's in unnamed namespace.
Edit: To evaluate it more, define the namespace as following:
// x.h
namespace
{
struct X
{
void foo(int x)
{
static int c; // static inside the function
cout<<"a = "<<(c++)<<endl;
}
};
}
Now #include this header file in 2 different .cpp files. In both of them try to call foo() with object of X. It will print:
a = 0
a = 0
Which means that X::foo() in both the .cpp files are different. If you give the namespace a name and repeat the same thing, it will output
a = 0
a = 1
Thus unnamed namespace creates a different copy for each translation unit.
It's legal in your scenario, but in one scenario, it will cause compiler ambiguous error.
In case have another class in X.h:
// X.h
struct X
{
void foo(int x) { }
};
And in foo.cpp, need to use the X defined in X.h
////////////////
// foo.cpp
#include "X.h"
namespace {
struct X
{
void foo(int x);
};
// use the X declared in anonymous namespace
void test()
{
X x;
x.foo(3);
}
}
// reference to 'X' is ambiguous
void X::foo(int x)
{
}
void otherFunction()
{
// Use struct X in X.h
::X x;
x.foo(3);
}
if leave the implementation code out of the anonymous namespace, compiler complains ambiguous. If move the implementation code inside anonymous namespace, it works fine.