I'm trying to have MAGMA as backend for Eigen in the same way it does already support MKL. While doing so I bump into the error above. The relevant snippets below:
template <>
/*ERROR IN THIS LINE >>>>>*/ inline void assign_scalar_eig2magma<magmaDoubleComplex,dcomplex>(magmaDoubleComplex& magmaScalar, const dcomplex& eigenScalar) {
magmaScalar.x=eigenScalar.real();
magmaScalar.y=eigenScalar.imag();
}
and the magmaDoubleComplex is defined in magma_types.h:
// ========================================
// define types specific to implementation (CUDA, OpenCL, MIC)
// define macros to deal with complex numbers
#if HAVE_CUBLAS
#include <cublas.h>
typedef cudaStream_t magma_queue_t;
typedef cudaEvent_t magma_event_t;
typedef int magma_device_t;
typedef cuDoubleComplex magmaDoubleComplex;
typedef cuFloatComplex magmaFloatComplex;
As far as I can see magmaDoubleComplex is declared but this doesn't seem to be the issue here ...
UPDATE: Indeed my mistake, here the template definition is "mkl" and it should be "magma".
template<typename MAGMAType, typename EigenType>
static inline void assign_scalar_eig2mkl(MAGMAType& magmaScalar, const EigenType& eigenScalar) {
magmaScalar=eigenScalar;
}
Related
I have built a mbed project with online ARMCC compiler, which has no complaints at all. After exporting projects to offline Keil MDK5. I got following complaints. Please advice if anyone knows how to remove/correct such issue.
SerialInterfaceProtocol/SerialInterfaceProtocol.h(16): error: #266: "CircularBuffer" is ambiguous
typedef CircularBuffer<uint8_t> SerialBuffer_t;
AlohaTransceiver/AlohaTransceiver.h(178): error: #266: "CircularBuffer" is ambiguous
CircularBuffer<AlohaFrame *> AlohaTxQueue;
AlohaTransceiver/AlohaTransceiver.cpp(44): error: #266: "CircularBuffer" is ambiguous
CircularBuffer<AlohaFrame *> AlohaRxQueue(10);
main.cpp(12): error: #266: "CircularBuffer" is ambiguous
CircularBuffer<uint8_t> SerialInputBuffer(128);
main.cpp(13): error: #266: "CircularBuffer" is ambiguous
CircularBuffer<uint8_t> SerialOutputBuffer(128);
I know CircularBuffer seems ambiguous if it has differenet types, but CircularBuffer is defined as a template, which should be used for different types? And online compiler passed, but MDK5 didn't, is there any compiler options should be enabled ?
The CircularBuffer is defined in RingBuffer.h
#ifndef RINGBUFFER_H_
#define RINGBUFFER_H_
#define DEFAULT_MAX_BUFFER_SZ 64
#include <stdint.h>
#include <stdlib.h>
template <typename T>
class CircularBuffer
{
private:
const size_t buffer_size;
size_t read_ptr;
size_t write_ptr;
size_t count;
// mutex lock
bool mux;
// overflow
bool is_over_flow;
// container
T *data;
public:
CircularBuffer(const size_t size=DEFAULT_MAX_BUFFER_SZ);
~CircularBuffer();
// psudo mutex
bool isLocked();
void lock();
void unlock();
// enqueue and dequeue
void enqueue(T in);
T dequeue();
// pointer operation
size_t getReadPtr();
size_t getWritePtr();
size_t getCounter();
// overflow
bool getOverFlow();
void clearOverFlow();
// operation
T first();
T last();
// random access
T operator[](size_t idx);
};
#endif
There are two CircularBuffer in the project, one is in mbed OS, the other is in user code. Merge them, or rename one of them.
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;
With the below code:
materia.h:
#ifndef MATERIA_H
#define MATERIA_H
class material
{
public:
template <class type>
static material* MakeMaterial(typename type::configtype, long);
template <class type>
void CreateNaturalForm(typename type::configtype, long);
…
};
template <class type>
material* material::MakeMaterial(typename type::configtype Config, long Volume)
{
return type::Spawn(Config, Volume);
}
#endif
materias.h:
#ifndef MATERIAS_H
#define MATERIAS_H
#include "materia.h"
#include "confdef.h"
class solid : public material {
public:
typedef solidmaterial configtype;
…
};
template material* material::MakeMaterial<solid>(solidmaterial, long);
template <class type>
void material::CreateNaturalForm(typename type::configtype Config, long Volume)
{
…
MakeMaterial(Config, Volume); // Error here
…
}
template void material::CreateNaturalForm<solid>(solidmaterial, long);
#endif
confdef.h:
#ifndef CONFDEF_H
#define CONFDEF_H
enum solidmaterial {
WOOD,
…
};
#endif
main.cpp
#include "materia.h"
#include "materias.h"
#include "confdef.h"
int main()
{
material::MakeMaterial(WOOD, 500); // Same error here
}
(Here's an online version of the above code that reproduces the error.)
I get the following compilation error message on the commented line:
No matching function for call to 'MakeMaterial'
What am I doing wrong? Shouldn't the explicit instantiation allow the compiler to see the correct function?
The code compiles if I write MakeMaterial<solid> explicitly, but the whole point here is to deduce type from the Config argument. How can I achieve this?
In the call
MakeMaterial(Config, Volume); // Error here
the compiler is asked to find a match where type::configtype in the function template, is the type of Config.
But nothing tells the compiler what to match type to: this is not an explicit instantiation.
In general there could be hundreds of types that type could be matched to, where type::configtype would be the type of Config. C++ does not support the special case where there is only one such possible type.
How to fix that depends on what you meant to accomplish.
main.c
#include "stackg.h"
int main()
{
return 0;
}
stackg.h
#ifndef STACKG_H
#define STACKG_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct stack_gt* stack_gt;
stack_gt stkg_init(
void* (*alloc)(const void* data, const int size),
void (*dealloc)(void* data),
void (*copy)(void* data_d, const void* data_s),
const int size
);
void stkg_free(stack_gt s);
int stkg_is_empty(stack_gt s);
int stkg_is_full(stack_gt s);
const int stkg_size(const stack_gt s);
void stkg_clear(stack_gt s);
int stkg_push(stack_gt s, const void* data);
int stkg_pop(stack_gt s, void* data);
int stkg_peek(stack_gt s, void* data);
#ifdef __cplusplus
}
#endif
#endif
The above program compiles successfully with the GCC compiler, but in MSVC2008 it gives the following error :
error C2040: 'stack_gt *' differs in levels of indirection from 'stack_gt'
What should I tell MSVC to make it compile the program without changing anything in the code?
Edit
Error occurs at line 8 of stackg.h :: typedef struct stack_gt* stack_gt;
Edit 2
If nothing else, I'll go with typedef struct _stack_gt* stack_gt;
The problem is that here:
typedef struct stack_gt* stack_gt;
you are giving stack_gt a different type, while this works fine:
typedef struct stack_gt* stack_gtB;
clang gives us a nicer error message:
error: typedef redefinition with different types ('struct stack_gt *' vs 'stack_gt')
This is covered in the draft C++ standard section 7.1.3 The typedef specifier paragraph 6:
In a given scope, a typedef specifier shall not be used to redefine the name of any type declared in that scope to refer to a different type. [ Example:
class complex { / ... / };
typedef int complex; // error: redefinition
—end example ]
Using the same name though is fine, so this would be ok:
typedef struct stack_gt stack_gt;
covered in paragraph 3:
In a given non-class scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers. [ Example:
typedef struct s { / ... / } s;
typedef int I;
typedef int I;
typedef I I;
—end example ]
Another idea:
#ifdef __cplusplus
extern "C" {
typedef void * stack_gt
#else
typedef struct stack_gt* stack_gt;
#endif
This is ugly, but you don't need to rewrite any other part of the code, only this header included in C++ . It is only used as an opaque pointer in C++ anyways, and C doesn't notice.
I have a code in VC2010 which I've reduced to a small example.
Test.h:
#pragma once
template <typename TPixel>
struct Image
{
typedef TPixel PixelType;
};
template <typename TImageType>
struct Operation
{
void DoOperation()
{
ImageType::PixelType value = 0;
// I've done a misprint here. It should be TImageType::PixelType
}
};
Test.cpp:
void Test()
{
typedef Image<char> ImageType;
Operation<ImageType> op;
op.DoOperation();
}
As I expected, that produces an error.
test.h(14): error C2653: 'ImageType' : is not a class or namespace name
Now, let's change test.cpp just a little bit.
typedef Image<char> ImageType;
void Test()
{
Operation<ImageType> op;
op.DoOperation();
}
Now it compiles! Surprisingly enough, ImageType in DoOperation() now matches with the global typedef in test.cpp.
My question: why does it compile? Is that a Visual C++ bug or a standard behavior?
I take it that test.cpp includes test.h before the typedef, so it's actually
#include "test.h"
typedef Image<char> ImageType;
void Test()
{
Operation<ImageType> op;
op.DoOperation();
}
Completed like this, it is indeed a bug, or standard nonconforming behavior with regard to two phase lookup. Names that do not depend on a template parameter should be resolved relative to the point of declaration of the template.
I guess this is known behavior.