I've got a couple of header/source files: FUNCS.h and FUNCS.cpp, MATRIX.h and MATRIX.cpp, and main.cpp
. In funcs and my MATRIX class there should be complex library, but when I try to include it in my MATRIX.h for example, I get error that complex is not a template.
Where should I include the library so all my headers would define complex as a template?
Example:
#pragma once
#include <complex>
class MATRIX
{
friend MATRIX sum(MATRIX a, MATRIX b);
friend MATRIX mult(MATRIX a, MATRIX b);
friend MATRIX vi4(MATRIX a, MATRIX b);
friend MATRIX operator * (const MATRIX& a, complex<int> b);
friend MATRIX operator * (complex<int> b, const MATRIX& a);
private:
complex<int>** M;
int m;
int n;
public:
MATRIX();
MATRIX(int _m, int _n);
MATRIX(int _m);
MATRIX(const MATRIX& _M);
complex<int> get(int i, int j);
void set(int i, int j, complex<int> value);
void Print();
MATRIX operator=(const MATRIX& _M);
complex<int>* operator[] (int index);
~MATRIX();
};
What is defined in <complex> is std::complex, what you are trying to use is complex, and the compiler cannot find something called complex in the global scope.
Change
friend MATRIX operator * (complex<int> b, const MATRIX& a);
to
friend MATRIX operator * (std::complex<int> b, const MATRIX& a);
Or introduce the name via
using std::complex;
but don't do that in a header! Rather put that in the source file only. The reason to not do it in a header is that all other code that includes the header will "inherit" it and it will lead to problems on the long run.
The header you should include in every file that uses std::complex.
Note that sometimes you can get away with including it indirectly, as in: a.h includes <complex>, b.h includes a.h hence it can use std::complex without expliticly including <complex>. Do not rely on that! It will cause trouble on the long run.
Further note that often a forward declaration is sufficient. It goes beyond what you have in your example, but I mention it for the sake of completeness. You don't need the definition in a header when all you use is pointers and references to a type. A declaration is sufficent in this case and the header can be included in the source only. This can reduce compilation time in huge projects.
Where should I include <complex>
In every file where you use the declarations of that file, before those usages. Conventionally, headers are included at the beginning (head) of the file
complex<int>** M;
I get error that complex is not a template.
<complex> doesn't declare ::complex. It declares std::complex. Use std::complex instead.
Related
The following code generates errors LNK2005 & LNK1169 on Visual Studio 2019.
LNK2005: "void__cdecl OverloadingPlus(void)" (?OverloadingPlus##YAXXZ) already defined in main.obj
LNK1169: one or more multiply defined symbols found
I reached this point by following a course on Udemy, where the instructor seems to have no problems with it.
Similar questions seem to be related to using global variables, defining functions in the header file, not using #ifndef guards... but as far as I can tell, that doesn't seem to be the case.
This problem started appearing only after the operator+ overload was included, but the operator<< doesn't trigger any errors, even though they have been declared and defined in the same manner.
Interestingly enough, if I remove any reference to OverloadingPlus.h file, and add #include Complex.h to main.cpp, the problem goes away.
I fail to see how including Complex.h in OverloadingPlus.h is contributing to a multiple definition of the operator+ exclusively, even though it is only included once in the entire project and the definitions are implemented in Complex.cpp and not in the header file, as pointed out in answers to similar problems.
Also tried surrounding the content of OverloadingPlus.h with an #ifndef statement just to make sure it is only used once which did not change a thing.
I attempted to declare a diferent operator+ overload inside the class (you can see it commented out), but it produces the same errors.
Commented all references to any other files trying to make sure Complex definitions are only included once. Didn't help either.
The code is the following:
main.cpp
//#include "OverloadingAssignmentOperator.h"
//#include "OverloadingLeftBitShiftOperator.h"
//#include "ComplexNumberClass.h"
#include "OverloadingPlus.h"
int main() {
//OverloadingAssignmentOperator();
//OverloadingLeftBitShiftOperator();
//ComplexNumberClass();
OverloadingPlus();
return 0;
}
OverloadingPlus.h
#ifndef OVERLOADING_PLUS_H
#define OVERLOADING_PLUS_H
#include "Complex.hpp"
using namespace complex;
void OverloadingPlus() {
Complex c1(1, 4);
Complex c2(3, 2);
std::cout << c1 + c2 << std::endl;
}
#endif
Complex.hpp
#ifndef COMPLEX_HPP
#define COMPLEX_HPP
#include <iostream>
namespace complex {
class Complex {
private:
double real;
double imaginary;
public:
Complex();
Complex(double, double);
Complex(const Complex&);
const Complex& operator=(const Complex& other);
//const Complex operator+(const Complex& r);
double getReal() const { return real; }
double getImaginary() const { return imaginary; }
};
Complex operator+(const Complex& l, const Complex& r);
std::ostream& operator<<(std::ostream& out, const Complex& c);
}
#endif // !__COMPLEX_HPP__
Complex.cpp
#include "Complex.hpp"
namespace complex {
Complex::Complex() : real(0), imaginary(0) {}
Complex::Complex(double r, double i) : real(r), imaginary(i) {}
Complex::Complex(const Complex& other) {
std::cout << "Copy constructor..." << std::endl;
real = other.real;
imaginary = other.imaginary;
}
const Complex& Complex::operator=(const Complex& other) {
real = other.real;
imaginary = other.imaginary;
return *this;
}
//const Complex Complex::operator+(const Complex& r) {
// return Complex(real + r.getReal(), imaginary + r.getImaginary());
//}
//
Complex operator+(const Complex& l, const Complex& r) {
return Complex(l.getReal()+r.getReal(), l.getImaginary()+r.getImaginary());
}
std::ostream& operator<<(std::ostream& out, const Complex& c) {
out << "(" << c.getReal() << "," << c.getImaginary() << ")";
return out;
}
}
The issue seems to be related to VS2019. Renaming the file to something different, rebuilding the project and renaming the file back to its original name fixed the issue.
While using inline as others suggested did circumvent the issue, it does not solve this specific problem as the conflicting file was not being included multiple times.
You forgot to "inline" your OverloadingPlus.
inline void OverloadingPlus() {
Complex c1(1, 4);
Complex c2(3, 2);
std::cout << c1 + c2 << std::endl;
}
should make the linker error go away.
What probably happened is: You have included "OverloadingPlus.h" in more than one compilation unit (although you failed to provide all instances of your #include in your question).
Every time you include "OverloadingPlus.h" in one of your .cpp files, you add another definition for void OverloadingPlus to your program. The linker detects this and cannot decide on "the right one" and so gives an error.
I am currently trying to create a wrapper interface that can translate C++ to C, and while studying on the possibilities to do that, I came across the template functions (and classes). Knowing that these functions can take any data type and return any data type as well, I find it hard to create a corresponding caller function name that C could read. A simple example is the adder.
template <class typesToAdd>
typesToAdd addStuff(typesToAdd a, typesToAdd b) {
return a + b;
}
My interface includes the extern "C" command to avoid the C++ name mangling in C.
Template is not a function that works for any data type. It is a template for a function that is created at compilation time. Each type you use creates a new function with a new symbol in the binary.
To export to C, you will have to specialize the type you want to use from C, like:
template <class typesToAdd>
typesToAdd addStuff(typesToAdd a, typesToAdd b) {
return a + b;
}
extern "C" {
int addStuffInt(int a, int b) {
return addStuff(a, b);
}
}
You may use function templates to simplify both implementing and maintaining the actual code that does the work but to provide a C interface, you'll still need to explicitly instantiate the functions for the types you aim to support.
If you'd like a C++ user to have the same restricted access to the functions as a C user will have, you can move the template implementation into the .cpp file and do the explicit instantiation there. A C++ user trying to use the function with types for which you have not explicitly instantiated the template will get a linking error.
It could look something like this:
// a.hpp
#pragma once
template <class T>
T addStuff(const T& a, const T& b); // no implementation here.
// a.cpp
#include "a.hpp"
#include "a.h"
template <class T>
T addStuff(const T& a, const T& b) {
T rv = a;
rv += b;
return rv;
}
// C interface - note: it's inside the .cpp file
extern "C" {
int add_ints(int a, int b) {
return addStuff(a, b);
}
double add_doubles(double a, double b) {
return addStuff(a, b);
}
}
/* a.h */
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
int add_ints(int, int);
double add_doubles(double, double);
#ifdef __cplusplus
}
#endif
A C user can now include the .h file and call the two functions for which you've provided an implementation.
Example:
// main.c
#include "a.h"
#include <stdio.h>
int main() {
printf("%d\n", add_ints(10, 20));
printf("%f\n", add_doubles(3., .14159));
}
Compilation:
g++ -c a.cpp
gcc -o main main.c a.o
The problem comes from a computer graphics C++ project in which I want to calculate gradient of both scale field and 3D-vector field. We know the gradient of them are different: scale field has 3D-vector gradient while 3D-vector field has a 3x3 matrix gradient. Since all other codes are the same, I am using template to reuse code. But I met with a problem in specializing member functions which has different code for calculating gradient of different data type. The minimized code is as follows:
//======== Main.cpp ========
#include "Render.h"
int main() {}
//======== Render.cpp ========
#include "Render.h"
//======== Render.h ========
#ifndef __RENDER_H__
#define __RENDER_H__
#include "VolumeGrid.h"
#endif
//======== VolumeGrid.h ========
#ifndef __VOLUMEGRID_H__
#define __VOLUMEGRID_H__
#include "Volume.h"
template < typename U >
class _Grid {
public:
const typename GradType<U>::GType grad(const Vector& x) const;
U * values = nullptr;
};
template <>
const Vector _Grid<float>::grad(const Vector& x) const {
return Vector();
}
template <>
const Matrix _Grid<Vector>::grad(const Vector& x) const {
return Matrix();
}
#endif
//======== Volumn.h ========
#ifndef __VOLUME_H__
#define __VOLUME_H__
#include "Vector.h"
#include "Matrix.h"
template <typename U>
struct GradType {
typedef int GType;
};
template<>
struct GradType<float> {
typedef Vector GType;
};
template<>
struct GradType<Vector> {
typedef Matrix GType;
};
template< typename U >
class Volume {
public:
typedef U volumeDataType;
typedef typename GradType<U>::GType volumeGradType;
};
#endif
//======== Vector.h ========
#ifndef __VECTOR_H__
#define __VECTOR_H__
class Vector {
public:
float xyz[3] = { 0,0,0 };
};
#endif
//======== Matrix ========
#ifndef __MATRIX_H__
#define __MATRIX_H__
class Matrix {
public:
float m[3][3];
};
#endif
The error message is:
build/Debug/GNU-Linux/Render.o: In function `Vector::Vector()':
/home/CppApplication_1/VolumeGrid.h:19:
multiple definition of `_Grid<float>::grad(Vector const&) const'
build/Debug/GNU-Linux/Main.o:/home/CppApplication_1/VolumeGrid.h:19:
first defined here
build/Debug/GNU-Linux/Render.o: In function
`_Grid<Vector>::grad(Vector const&) const':
/home/CppApplication_1/VolumeGrid.h:24:
multiple definition of `_Grid<Vector>::grad(Vector const&) const'
build/Debug/GNU-Linux/Main.o:/home/CppApplication_1/VolumeGrid.h:24:
first defined here
As you can see from the code, the two specialized grad function corresponding to different data types are defined only once in VolumeGrid.h, as member function of class Grid<float> and Grid<Vector>, respectively. But the error message says there are multiple definitions of them. The code is compiled with g++ 4.8.4 with C++11 enabled on ubuntu 14.04 64-bit (it compiles well on Visual Studio 2015). The code above is minimized in that removal of any line, e.g., #include "Render.h" in Main.cpp, will make the error disappear. The header inclusion structure and class inheritance hierarchy should not be changed because they are used in actual project. So could you please tell me where is the problem in specializing the grad function and how to fix it? Thanks a lot for your help.
An explicit function template specialization (having no template parameters) is not implicitly inline like actual templates are.
Either move the definitions to a *.cpp file, or mark them inline.
If you move them to a *.cpp file, you should declare them in the header file, like
template <>
const Vector _Grid<float>::grad(const Vector& x) const;
I am using OpenCV for some image manipulation and it has several functions that must be given a data type to perform correctly. My idea is to template these functions so I do not have to write a separate function for each possible data type it could be.
However, the code I would like the code I am writing to be compatible with some existing C code I have that stores images in memory so I can pass it around easier without writing the image to disc constantly.
The problem I am running into is how to make my .h files and libraries to let the C program call the C++ template functions. I have not had a chance to try it yet, but so far what I have would look something what follows:
foo.h
int foo(int a, int, b);
float foo(float a, float b);
foo.c:
int foo(int a, int b) {
return footemp(a, b);
}
float foo(float a, float b) {
return footemp(a, b);
}
foo.hpp:
template<class t>
t footemp(t a, t b) {
return a + b;
}
Which does not work since it requires my .c file to know about a templated file.
So I am open to suggestions. Thank you in advance for the help
This is possible, with some care. Use a C++ source file foo.cpp:
#include "foo.h"
#include "footemp.hpp"
int foo_int(int a, int b) {
return footemp(a, b);
}
float foo_float(float a, float b) {
return footemp(a, b);
}
In foo.h, use extern "C" to make C-compatible declarations, with an #ifdef to allow use as either C or C++:
#ifdef __cplusplus
extern "C" {
#endif
int foo_int(int a, int, b);
float foo_float(float a, float b);
#ifdef __cplusplus
}
#endif
Compile this as a C++ library—static or dynamic, it doesn’t matter. In your C sources you can now #include "foo.h" and use these functions as you would expect, so long as you link against the library.
I imagine one thing you could do is write the function in C++, declaring the specializations you want, and at the same time defining extern "C" functions that forward the calls to the template functions.
Keep in mind if you're using C for the other stuff, you're going to need to name the functions different; C doesn't do function overloading.
As mday299 mentioned, there is no templates in C.
However, if your C code is contained in a saparate compilation unit (.exe/.dll), you can provide C interface for your template functions almost like you did it:
foo.h
/* C interface */
int fooInt(int a, int, b);
float fooFloat(float a, float b);
foo.hpp
template <class T> foo(T a,T b)
{
return a+b;
}
foo.cpp:
#include "foo.h"
#include "foo.hpp"
int fooInt(int a, int b) {
return foo<int>(a, b);
}
float fooFloat(float a, float b) {
return foo<float>(a, b);
}
Then, project would be compiled separate using c++, and c part would see only foo.h and lib/dll file
No templates in C. That's a C++ feature. Sorry.
There is a good chance that you'll be able to compile your C file with a C++ compiler. So you can build your whole project, both C and C++ sources with a C++ compiler.
You are already compiling it with a C++ compiler, otherwise you wouldn't be able to compile your overloaded foo functions.
I thought that friend functions could access class variables as in how I try to do v.x, v.y, v.z in the << function. But it doesn't compile. It says it's unable to resolve identifier at those lines.
Also I'm trying to learn how to use namespaces. Even though I use the namespace vec in the implementation file I still have to include Vector:: before everything so what's the point?
Header file:
#ifndef VECTOR_H
#define VECTOR_H
namespace vec {
class Vector {
private:
double x, y, z;
public:
Vector(double, double, double);
friend std::ostream& operator<<(std::ostream&, const Vector&);
};
}
#endif /* VECTOR_H */
.cpp file:
#include "Vector.h"
#include <iostream>
using namespace vec;
//Constructor
Vector::Vector(double x1 = 0, double y1 = 0, double z1 = 0) {
x = x1;
y = y1;
z = z1;
}
//Have also tried adding vec:: and Vector:: before operator<< here.
std::ostream& operator<<(std::ostream& out, const Vector& v) {
out<<"<"<<v.x<<", "<<v.y<<", "<<v.z<<">";
return out;
}
I believe part of the problem is that your vec.h doesn't have #include <iostream>, so the type std::ostream is unidentified in that file, and since that part is compiled before the vec.cpp main part, it fails to recognise your function.
You also need to put your operator<< into the namespace of vec. After all, you have asked for a friend function within that namespace.
With these two changes, your code compiles with gcc -Wall -Wextra -O2.
Your compile error may relative to below issues:
Default parameter only goes to function declaration not function
definition, you are doing the other way around.
Also, in Vector.cpp you should wrap up your class member function
definitions in namespace instead of calling using directive.
Try:
Vector.h
#include <iostream>
class Vector {
private:
double x, y, z;
public:
Vector(double x1 = 0, double y1 = 0, double z1 = 0);
^^ ^^ ^^
friend std::ostream& operator<<(std::ostream&, const Vector&);
};
Vector.cpp
namespace vec
{
Vector::Vector(double x1, double y1, double z1)
:x(x1), y(y1), z(z1)
{
}
}
The friend std::ostream& operator<< declaration appears in namespace vec, so the definition should be prefixed by vec::. Your comment says you tried that - maybe you got confused by the other error messages billz documents, but you should reinstate vec::operator<< or surround it with namespace vec { ... }.
This creates an error like:
ns.cc: In function `int main()':
ns.cc:26: error: ambiguous overload for 'operator<<' in 'std::cout << w'
ns.cc:19: note: candidates are: std::ostream& operator<<(std::ostream&, const vec::Vec&)
ns.cc:10: note: std::ostream& vec::operator<<(std::ostream&, const vec::Vec&)