Can't pass shared pointer as parameter to function definition? - c++

If I place a function declaration with a shared pointer as a parameter and its definition in the header, everything compiles fine, but attempting to separate them into a .hpp and .cpp file causes compilation errors like:
Use of undeclared identifier 'std' //Solved via including <memory> & <cstdint>
Variable has incomplete type 'void' //Solved via including <memory> & <cstdint>
Use of undeclared identifier 'uint8_t' //Solved via including <memory> & <cstdint>
For example:
For this main: main.cpp
#include <iostream>
#include "example1.hpp" //Switch out with "example2.hpp"
int main(int argc, const char * argv[]) {
std::shared_ptr<uint8_t> image = 0;
foo(image);
return 0;
}
This Works:
example1.hpp
#ifndef example1_hpp
#define example1_hpp
#include <stdio.h>
void foo(std::shared_ptr<uint8_t> variable) { }
#endif /* example1_hpp */
This does not work:
example2.cpp
#include "example2.hpp"
void foo(std::shared_ptr<uint8_t> variable) { }
example2.hpp
#ifndef example2_hpp
#define example2_hpp
#include <stdio.h>
void foo(std::shared_ptr<uint8_t> variable);
#endif /* example2_hpp */
How do I separate the declaration and definition for this function into separate files successfully?

You have wrong includes. <stdio.h> is a C header. To use shared_ptr you need to include <memory>, to use uint8_t you need to include <cstdint>.

Related

Declare variable in namespace, define it in main, make it visible to all other files [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 3 years ago.
Using C++14, I'm trying to define a variable in a namespace where commonly used variables are stored (App::Common). The main function should be the one that sets it, since it gets set to argv[0]. Meanwhile I need the variable to be visible by all other classes/files. But I get the linker error shown below. Also, ideally I would like the variable to be const where only the main function would set it once.
common.hpp
#pragma once
#include <string>
namespace App{
namespace Common{
extern std::string appPath;
}
}
main.cpp
#include "common.hpp"
#include "client.hpp"
#include <string>
int main() {
App::Common::appPath = argv[0];
}
client.hpp
#include "common.hpp"
class Client {
public:
void printAppPath();
};
client.cpp
#include <iostream>
#include <string>
#include "common.hpp"
#include "client.hpp"
void Client::printAppPath() {
std::cout << App::Common::appPath << std::endl;
}
I get the following error by the linker:
ld: main.o: in function `main':
main.cpp:(.text.startup.main+0x25): undefined reference to `App::Common::appPath[abi:cxx11]'
ld: Client.o: in function `Client::printAppPath()':
Client.cpp:(.text...): undefined reference to `App::Common::appPath[abi:cxx11]'
This
#pragma once
#include <string>
namespace App{
namespace Common{
extern std::string appPath;
}
}
contains only declaration of the variable appPath without its definition.
Here
#include "common.hpp"
#include "client.hpp"
#include <string>
int main() {
App::Common::appPath = argv[0];
}
there is used the assignment operator to assign a value tp the variable appPath as if it were already defined. However actually its definition does not yet exist.
You can define the variable in any module in any enclosing namespace of the namespace Common or inside the namespace. For example you could define it in client.cpp like
std::string App::Common::appPth;
You are mixing definition and assignment, which are two different things for a variable:
a declaration for a variable x tells your compiler that there exists somewhere a variable named x;
a definition for a variable x tells your compiler that it needs to reserve some space for this variable x, and that the variable x will live at this location;
an assignment assigns a value to a variable.
For a variable, a declaration is usually a definition:
void foo() {
int a; // Declaration AND Definition!
}
...except when the variable is marked as extern, since extern explicitly tells the compiler that this variable is defined elsewhere. In your case, this:
namespace App::Common { // C++17 style
extern std::string appPath;
}
...is a declaration, but this:
namespace App::Common { // C++17 style
std::string appPath;
}
...would be a definition (and also a declaration), and this:
int main(int argc, char *argv[]) {
App::Common::appPath = std::string(argv[0]);
}
...is an assignment.
You should not define appPath in a header such as common.hpp, otherwize, you will have multiple definitions of the same variable (one for each .cpp file that includes your common.hpp) and the program will fail to compile.
What you want is a single definition for your program, and the only way to obtain it is to define App::Common::appPath once-and-for-all in a .cpp file. You can define it in main.cpp if you want:
#include <string>
#include "common.hpp"
#include "client.hpp"
// Definition:
std::string App::Common::appPath;
int main() {
// Assignment:
App::Common::appPath = argv[0];
}
You need definition:
in Common.cpp:
namespace App{
namespace Common{
std::string appPath;
}
}

g++ how to solve warning "used but never defined"? (not static or inline)

I have come across a strange compile error that I cannot make sense of. Firstly the error refers to the function as if it was in an anonymous namespace, however it is in fact inside namespace database. Secondly the "used but never defined" statement suggests that the compile requires me to define the function from within the header. The function is in fact declared in a separate implementation file. However the function is neither static nor inline so I am at a loss as to why it requires a definition in the header. It is a requirement that this piece of code is strictly compliant, because of this I have compiled with both -Wall -Werror. I have also included a shortened version of my source code for clarification.
Note: This question is different from other similar questions asked here in that it does not involve static or inline functions.
Error:
In file included from src/main.cpp:6:0:
include/database.hpp:19:6: error: 'void {anonymous}::SetupSettings()' used but never defined [-Werror]
void SetupSettings();
^
cc1plus.exe: all warnings being treated as errors
main.cpp
#include <iostream>
#include "config.hpp"
#include "database.hpp"
int main() {
database::SetupSettings();
return 0;
}
database.hpp
#ifndef database
#define database
#include <iostream>
#include "config.hpp"
#include "sqlite/sqlite3.h"
namespace database {
extern sqlite3* settings_database;
void SetupSettings();
// ^^ Apparent warning here.
} // namespace database
#endif
database.cpp:
#include <iostream>
#include <vector>
#include "config.hpp"
#include "database.hpp"
#include "sqlite/sqlite3.h"
namespace database {
sqlite3* settings_database;
void SetupSettings() {/*More code here*/}
} // namespace database
The problem is caused by use of:
#ifndef database
#define database
After that,
namespace database { ...
is seen as
namespace { ...
i.e. an anonymous namespace.
You need to use a different include guard macro, such as:
#ifndef database_hpp
#define database_hpp

C++: Accessing data of dynamic structures within extern function

I have a problem with passing dynamically allocated structures to a function and accessing it's content.
The program uses mex to pass data from Matlab to C++. I use Visual Studio.
The structure I define in a header in 'InOut.h'
#include <string>
#include <cstdint>
#include <cstdlib>
struct sObjects {
std::string Type;
float *Position;
};
typedef struct sObject sObject;
In the main function I than allocate the structure is in 'MainFcn_Mex.cpp'
#include "MainFcn_Mex.h"
// ...
// get number of Objects from Matlab
int N_Obj = mxGetNumberOfElements(prhs[1]);
sObjects *Objects = new sObjects[N_Obj];
for (int k=0; k<N_Obj; k++) {
// get the pointer pointer map
pMap = mxGetField(prhs[1],k,"Type");
Objects[k].Type = mxArrayToString(pMap);
// get the pointer pointer map
pMap = mxGetField(prhs[1],k,"Position");
// setting pointer to the first Element
Objects[k].Position = (float*)mxGetPr(pMap);
mexPrintf("Objects(%d,1).Type: %s \n", k+1, Objects[k].Type);
}
create_Objects(Objects, N_Obj);
The function create_Objects is in a differente file 'create_Objects.cpp' and included via 'MainFcn_Mex.h':
#include <stdio.h>
#include <direct.h>
#define _USE_MATH_DEFINES
#include "math.h"
#include <cmath>
#include "mex.h"
#include "matrix.h"
#include <cuda.h>
#include <cuda_runtime.h>
#include "device_launch_parameters.h"
#include "InOut.h"
void create_Objects(sObjects *Objects, int N_Obj);
The content of 'create_Objects.cpp' so far is:
#define _USE_MATH_DEFINES
#include "math.h"
#include <cmath>
#include "InOut.h"
#include "mex.h"
void create_Objects(sObjects *Objects, int N_Obj)
{
for (int k=0; k<N_Obj; k++) {
mexPrintf("Objects(%d,1).Type: %s \n", k+1, Objects[k].Type);
}
}
Visual Studio tells me:
"error C2676: binary '[' : 'sObjects' does not define this operator or
a conversion to a type acceptable to the predefined operator"
Why can I access the data in the main function and not in seccondary functions?
How can I access a dynamically allocated structure in other functions, when its size isn't known at compile time?
Thanks a lot for your time!
It looks like you are trying to use struct directly as a typedef. Simply add typedef to your struct definition, will turn it into a type.
Like this:
... #include "mex.h"
typedef struct sObjects {
std::string Type;
float *Position;
};
(Otherwise you should use the full struct keyword as in void create_OpticsObjects(struct sObjects &Objects, int N_Obj).)
Your function prototypes don't need the extern qualifier.
You don't need extern unless you want globals variables. You seem to want simply global structs or types in your example, so extern is not required.
Using extern for globals
What you could be referring to is an instance of your object (or a pointer to your object), and that can be made global by using extern. as in this excerpt from the header file:
... #include "mex.h"
typedef struct sObjects {
std::string Type;
float *Position;
};
extern sObjects *pointerToOnesObjects;
Then in ONE source file, you need to declare the 'real' variable as in (this is good to initialise it here):
sObjects *pointerToOnesObjects = NULL;
With this method your variable pointerToOnesObjects is now available globally (in all your source files that use the same header file).

Blitz++ arrays as global arrays

I am working on a project in C++ which has many functions. I don't want to write them in the main program and would like to write a separate .cpp file for each of the functions. Most of these functions will act on some arrays, so I wish to make these arrays global. So I declared all the arrays in a separate .cpp file called globals.cpp and put them in a globals.h file prefixed with extern. The I wrote the functions and the main program as usual, however when I compile, I get an
Here is what I have:
//globals.cpp
#include <iostream>
#include <blitz/blitz.h>
#include <blitz/array.h>
#include "prototype.h"
#include "globals.h"
BZ_USING_NAMESPACE(blitz)
Array<double,2> A(5,5);
In the globals.h file I have
#ifndef GLOBALS_H
#define GLOBALS_H
extern Array<double,2> A(5,5);
#endif
Then I have a function add.cpp, for example
#include <iostream>
#include <blitz/blitz.h>
#include <blitz/array.h>
#include "prototype.h"
#include "globals.h"
BZ_USING_NAMESPACE(blitz)
void add.cpp(){
for(int i=0;i<5;i++){
A(i,i)=i*i;
}
}
I obviously include it in the prototype.h file
#ifndef GLOBALS_H
#define GLOBALS_H
void add();
#endif
Finally I have the main program mainprog.c
#include <iostream>
#include <blitz/blitz.h>
#include <blitz/array.h>
#include "prototype.h"
#include "globals.h"
BZ_USING_NAMESPACE(blitz)
int main(){
add();
cout<<A<<endl;
return 0;
}
However when I compile I get the error `globals.h:6:8: error: ‘Array’ does not name a type
and then an error in the add.cpp function saying the error A was not declared.
How do I declare the blitz arrays as global?
Thank you
`
The issue is that your macro to import the namespace(BZ_USING_NAMESPACE) is below your include of globals.h. Thus the Array class you are trying to reference in globals.h is actually blitz::Array or something at that point.
For a simple fix, simply use the BZ_USING_NAMESPACE in globals.h right above your declaration for A.
Always remember to include everything a header file needs in that header file.
#ifndef GLOBALS_H
#define GLOBALS_H
#include <blitz/blitz.h> //No idea if the Array class needs this header.
#include <blitz/array.h>
BZ_USING_NAMESPACE(blitz)
extern Array<double,2> A(5,5);
#endif

typedef across same namespace in different header files

I'm currently learning c++ and struggling with some code:
Garden.h:
#ifndef GARDEN_H_
#define GARDEN_H_
#include <vector>
#include <boost/tr1/memory.hpp>
#include "Shape.h"
#include "Utils.h"
namespace cma {
typedef boost::shared_ptr<cma::Shape> ShapePtr;
typedef std::vector<cma::ShapePtr> GardenPlan;
}
#endif /* GARDEN_H_ */
Utils.h:
#ifndef UTILS_H_
#define UTILS_H_
#include "Garden.h"
namespace cma {
void printList(GardenPlan const & p, std::ostream & o);
}
#endif /* UTILS_H_ */
The compiler output:
In file included from ../src/Garden.h,
from ../src/Utils.cpp:
../src/Utils.h: error: variable or field 'printList' declared void
../src/Utils.h: error: 'GardenPlan' was not declared in this scope
../src/Utils.h: error: expected primary-expression before '&' token
../src/Utils.h: error: 'o' was not declared in this scope
I seriously just don't get it.
You have a cyclical include problem.
You're including Garden.h in Utils.h and Utils.h in Garden.h.
You either need to put both definitions in the same header file or forward declare one of the types.
However, you don't actually need to include Utils.h in Garden.h so removing that include should solve your problem.