I try to run a .cpp with a .hpp file in Linux using this command: g++ -c main.cpp but I have this error about calloc():
error: there are no arguments to ‘calloc’ that depend on a template parameter, so a declaration of ‘calloc’ must be available [-fpermissive]
Tr=(T *)calloc(Rows*Colomns, sizeof(T));
In member function ‘T* MyMatrix::Adjoint()’:
MyMatrix.hpp:276:35: error: there are no arguments to ‘calloc’ that depend on a template parameter, so a declaration of ‘calloc’ must be available [-fpermissive]
Temp = (T*)calloc(N*N, sizeof(T));
I noticed that this code works in Microsoft Visual Studio:
#pragma once
#include <iostream>
#include <fstream>
template <typename T>
class MyMatrix {
private:
int Rows;
int Colomns;
T* A; //Matricea
T* Tr; //Transpusa acesteia
float* Inv; //Inversa
public:
MyMatrix(int L, int C)
{
Rows = L;
Colomns = C;
A = (T*)calloc(Rows * Colomns, sizeof(T));
if (A == NULL)
throw("Eroare la alocarea matricii! :(");
}
MyMatrix(T* S, int L, int C)
: MyMatrix(L, C)
{
for (int i = 0; i < Rows * Colomns; ++i)
A[i] = S[i];
}
~MyMatrix() { free(A); }
void Transposed()
{
Tr = (T*)calloc(Rows * Colomns, sizeof(T));
for (int i = 0; i < Colomns; ++i)
for (int j = 0; j < Rows; ++j)
Tr[j * Colomns + i] = A[i * Rows + j];
}
void Inverse()
{ //some code
T* Adj = Adjoint();
Inv = (float*)calloc(Rows * Rows, sizeof(float));
for (int i = 0; i < this->Rows * this->Rows; ++i)
Inv[i] = Adj[i] / (float)Det;
}
};
#endif // MYMATRIX_HPP_INCLUDED
a declaration of ‘calloc’ must be available
The solution is to declare calloc before using it. Since it is a standard function, it must be declared by including the standard header that is specified to declare it.
calloc is declared in the header <stdlib.h>. Note that the .h suffixed headers from the C standard library are deprecated in favour of using the c prefixed headers such as <cstdlib>. However, the c prefixed headers declare the functions in the std namespace which you have failed to use in this case.
So the complete solution is to include <cstdlib>, and use std::calloc.
However, you don't need to use calloc at all. Better solution is to use std::make_unique or std::vector.
As the error message suggests, the g++ compiler used here does not have an implementation wherein the second parameter is a template type i.e. the compiler recognizes the arguments when the second argument is of type int or float because these are the types the compiler knows about its 'calloc' implementation works with these types BUT it does not recognize when the second argument is of a templated type.
Visual Studio used here probably has an implementation which allows template types to be passed to 'calloc'.
Maybe you can try updating the g++ compiler to the latest and then it might support what you are trying to do here.
hope this helps!
Related
It seems to me that clang has some problems when using omp collapse in template function.
I've attached a minimal example. Clang (9, 10, 11) can't compile it, while gcc compiles it just fine. Is this a compiler error or is my code doing something illegal?
Making this function non template or dropping the collapse clause makes it compile just fine.
#include <vector>
#include <iostream>
template <typename T>
void test(const std::vector<int> begin_vec) {
#pragma omp parallel for collapse(2)
for (int n = begin_vec.at(0); n < 0; n++) {
for (int h = begin_vec.at(1); h < 1; h++) {
for (int w = begin_vec.at(2); w < 2; w++) {
std::cout << n + h + w << std::endl;
}}}
}
int main() {
test<int>({0,0,0});
}
To compile clang++-10 -fopenmp test.cpp
For me, clang produces the following error
test.cpp:9:16: error: 'this' argument to member function 'at' has type 'const std::vector<int>', but function is not marked const
for (int h = begin_vec.at(1); h < 1; h++) {
^~~~~~~~~
test.cpp:16:3: note: in instantiation of function template specialization 'test<int>' requested here
test<int>({0,0,0});
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/stl_vector.h:1092:7: note: 'at' declared here
at(size_type __n)
^
(I've also tried to use libc++, but it didn't change anything)
Greetings and thank you in advance!
I'm working in macOS X 10.12; Eclipse Neon 4.6, Compiling using macOS X GCC. I am receiving the following error:
../matrix.h:82:1: error: 'Matx' is not a class, namespace, or enumeration
`Matx::~matx(){`
`^`
`../matrix.h:27:7: note: 'Matx' declared here`
The error is confusing due to the following matrix.h file:
#ifndef MATRIX_H_
#define MATRIX_H_
#include <iostream>
template <class T>
class Matx {
int ROWS, COLS ;
int colix[COLS], rowix[ROWS] ;
T ** array ;
Matx(int, int) ;
~Matx() ;
void rowSwap() ;
void size( void ) ;
void swapRows(int i1, int i2) { std::swap(this->array[i1], this->array[i2]); }
void printMat( void ) ;
};// end class matrix
template <class T>
Matx::~Matx(){
delete this->array ;
}// end ~matx()
Note there are a few more functions in the file, but the error is consistent across all of them. I have tried defining the functions with scope resolution and without, i.e. Matx::~m but to no avail. Any help is much appreciated!
You should write the definition of the function like this:
template <class T>
Matx<T>::~Matx(){
delete this->array ;
}// end ~matx()
This Part is wrong.
int ROWS, COLS ;
int colix[COLS], rowix[ROWS] ;
your're defining arrays of size COLS and ROWS. But these are non-const member variables. You need compile time expressions. For example:
static constexpr int ROWS = 4;
static constexpr int COLS = 4;
I have a .cu file that when compiled on its own, right click and select compile, it compiles just fine, but when I have another header file, a c++ header file, that calls this .cu file the build fails. The .cu file properties have been edited to build with the CUDA compiler. The errors that I am getting are 'blockIdx': undeclared identifier 'blockDim': undeclared identifier, etc.. basically errors that I would expect compiling cuda code with a c++ compiler. So is it possible to include a .cu cuda code in a c++ header?
Here is the .cu file:
Matrix.cu
#include <cuda.h>
#include <cuda_runtime.h>
#include <cuda_device_runtime_api.h>
#define BLOCKSIZE 32
using namespace std;
template<typename T> class Matrix
{
public:
typedef T value_type;
~Matrix();
Matrix();
Matrix(int rows, int columns);
int height;
int width;
int stride;
size_t size;
void CreateIdentity(Matrix<T>&I);
private:
vector<T> elements;
T* firstElement;
};
template<typename T>
Matrix<T>::~Matrix()
{
}
template<typename T>
Matrix<T>::Matrix()
{
}
template<typename T>
Matrix<T>::Matrix(int rows, int columns)
{
height = rows;
width = columns;
stride = columns; //in row major order this is equal to the # of columns
elements.resize(rows*columns);
firstElement = elements.data();
size = height*width*sizeof(T);
}
__global__ void IdentityMatrixKernel(float* identity, int size)
{
int index_x = blockIdx.x * blockDim.x + threadIdx.x;
int index_y = blockIdx.y * blockDim.y + threadIdx.y;
// map the two 2D indices to a single linear, 1D index
int grid_width = gridDim.x * blockDim.x;
int index = index_y * grid_width + index_x;
// map the two 2D block indices to a single linear, 1D block index
//int result = blockIdx.y * gridDim.x + blockIdx.x;
// write out the result
if (index % (size+1))
{
identity[index] = 0;
}
else
{
identity[index] = 1;
}
}
template<typename T>
void Matrix<T>::CreateIdentity(Matrix<T>&I)
{
float* d_I;
int size1 = I.height;
int size2 = I.height*I.width*sizeof(float);
cudaMalloc(&d_I,size2);
dim3 block_size;
block_size.x = BLOCKSIZE;
block_size.y = BLOCKSIZE;
dim3 grid_size;
grid_size.x = size1/ block_size.x + 1;
grid_size.y = size1/ block_size.y + 1;
IdentityMatrixKernel<<<block_size,grid_size>>>(d_I,size1);
cudaMemcpy(I.GetPointer(),d_I,size2,cudaMemcpyDeviceToHost);
cudaFree(d_I);
}
And here is the header file that #include "Matrix.cu"
Element.h
#pragma once
#include "Matrix.cu"
#include <vector>
using namespace std;
class Element
{
public:
Element(void);
~Element(void);
Element(int iD, float k, vector<int> nodes);
Element(int iD, vector<int> nodes, int pId);
void SetElementType(DOF type);
DOF GetElementType();
int GetNodeId(int index);
int GetNodesPerElement();
int GetPartId();
void CalculateShapeFunctions(Matrix<int> spaceCoordinates);
void CalculateSShapeDerivative(Matrix<int> spaceCoordinates);
void CalculateTShapeDerivative(Matrix<int> spaceCoordinates);
Matrix<float> GetShapeFunctions();
float GetSShapeDerivative(int row, int column);
float GetTShapeDerivative(int row, int column);
void SetStrainDisplacement(Matrix<float> B);
Matrix<float> GetStrainDisplacement();
private:
int elementId;
float stiffness;
vector<int> nodeIds;
DOF elementType;
int partId;
Matrix<float> shapeFunctions;
Matrix<float> sShapeDerivative;
Matrix<float> tShapeDerivative;
Matrix<float> strainDisplacement;
};
EDIT:
So I have been directed to try and separate the template class member functions implementing cuda into a .cu file while keeping the template class definition and any template member functions not using cuda in the original header file. This does seem on the right path, c++ compiler compiles the .h file while the cuda compiler does the .cu, but I am having trouble getting rid of link errors. I understand that I need to explicitly instantiate my template class for the types I need in the .cu file to avoid link errors, but I seem to still get them.
I instantiated my template class at the end of the .cu file as follows:
template class Matrix<float>;
template class Matrix<int>;
template class Matrix<string>;
I am now getting link errors to the template member functions using cuda.
Answer: .cu files cannot be used as #include "file.cu" like header files because they will be compiled with the C++ compiler not cuda. The solution was to move anything implementing cuda into a separate .cu file while still keeping the definitions of the template functions inside the template class definition in the header, and adding an #include "file.h" in the file.cu. To solve any link errors with the template function declarations that were moved to a .cu file, an explicit instantiation of the template class was added to the bottom of the header file. Since only float types were used in the template functions using cuda, only an instantiation of type float was added: template class Matrix. The above solution compiled and ran perfectly.
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Why do I get "unresolved external symbol" errors when using templates? [duplicate]
(3 answers)
Closed 9 years ago.
I have 3 files - main, Array.hh, and Array.cc. When I do "g++ main.cc Array.cc", I get all kinds of linker errors, e.g.: "undefined reference to Array<<\double>>::Array(int)"
I read the other stackoverflow entries for linker errors with templates, but they are recommending to split the HH and CC files, which I have already done. So what can be the problem here?
Edit: Thanks for the replies. I had not understood the posts I had read previously. Merging the Array.cc into the Array.hh solves the problem. Closed.
main.cc:
#include "Array.hh"
#include <iostream>
int main() {
Array<int> anArray(12);
Array<double> adArray(12);
for (int nCount = 0; nCount < 12; nCount++) {
anArray[nCount] = nCount;
adArray[nCount] = nCount + 0.5;
}
for (int nCount = 11; nCount >= 0; nCount--)
std::cout << anArray[nCount] << "\t" << adArray[nCount]
<< std::endl;
return 0;
}
Array.hh:
template <typename T>
class Array {
private:
int m_nLength;
T *m_ptData;
public:
Array();
Array(int nLength);
~Array();
void Erase();
T& operator[](int nIndex);
int GetLength();
};
Array.cc
#include "Array.hh"
template <typename T>
Array<T>::Array() {
m_nLength = 0;
m_ptData = 0;
}
template <typename T>
Array<T>::Array(int nLength) {
m_ptData= new T[nLength];
m_nLength = nLength;
}
template <typename T>
Array<T>::~Array() { delete[] m_ptData; }
template <typename T>
void Array<T>::Erase() {
delete[] m_ptData;
m_ptData= 0;
m_nLength = 0;
}
template <typename T>
int Array<T>::GetLength() { return m_nLength; }
Put the definitions from Array.cc into Array.hh
When a template class is used, a class is created. Array.cc does not know which classes should be created from the template, only main.cc knows that. main.cc does not know how to create the classes, because it does not know the definition of the member functions of Array, only Array.cc knows that.
You need to #include "Array.cc"
A template can't be instantiated if its definition is not available.
This separation of definition and declaration is fine, but you must include the cc file whereever you are instatiating that template with a new type
Recommendations you took are not very accurate. You should not separate your templates into .h and .cpp files.
If you insist on putting them separate, "export" is the keyword you are looking for.
For more information about "export" check here: http://www.parashift.com/c++-faq/separate-template-fn-defn-from-decl-export-keyword.html.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why can templates only be implemented in the header file?
What is an undefined reference/unresolved external symbol error and how do I fix it?
I have defined a template class in a file.
point.h is
#ifndef POINT_H
#define POINT_H
using namespace std;
template <typename T, int size>
class point {
private:
T coordinates[size];
public:
point();
void set_coordinates(const T *);
void get_coordinates(T *);
};
#endif /* POINT_H */
point.c is
#include "point.h"
template <typename T, int size>
point::point() {
for (int i = 0; i < size; i++)
coordinates[i] = 0;
}
template <typename T, int size>
void point<T, size>::set_coordinates(const T *coordinates) {
for (int i = 0; i < size; i++)
this->coordinates[i] = coordinates[i];
}
template <typename T, int size>
void point<T, size>::get_coordinates(T *coordinates) {
for (int i = 0; i < size; i++)
coordinates[i] = this->coordinates[i];
}
I am using this template as point<int, 2> p0;. But compiler gives error that point<int, 2> is not defined.
I searched on this and found two solutions -
1. to use export variable. But I read that it is not supported by all compilers. So, I don't want to use that.
2. to create explicit class specializations like
template <> class point<int> {
...
}
But isn't there any other way to do this? (I mean in C++ standard containers, they might have used some technique to do this.)
Read this and the next two FAQ questions - C++ FAQ
The solution of the c++ standard containers is keep everything in the header file.
You should put all the definitions belonging to the template point (that is, including the member functions) to the point.h file and include it in any file that uses the point class, so that the compiler can instantiate it as needed. See this question for details.
The C++ compilers and linkers have means to avoid "multiple definitions" error on link (the ODR rule in the standard states this must be the case).