I want to decloare a function pointer as:
char*(*palpr_recognize_rawimage)(OPENALPR*, unsigned char*, int, int, int, struct AlprCRegionOfInterest);
which is for a function prototype declared as:
char *openalpr_recognize_rawimage(OPENALPR *instance, unsigned char *pixelData, int bytesPerPixel, int imgWidth, int imgHeight, struct AlprCRegionOfInterest roi)
but I get this error on compilation:
‘char* (* palpr_recognize_rawimage)(OPENALPR*, unsigned char*, int, int, int, AlprCRegionOfInterest)’ redeclared as different kind of symbol
char*(*palpr_recognize_rawimage)(OPENALPR*, unsigned char*, int, int, int, struct AlprCRegionOfInterest);
^
One way to avoid retyping a complex definition and possibly making an error is to use decltype.
So, after your function prototype you can have:
using PFN = decltype(&openalpr_recognize_rawimage);
PFN myfunctionptr;
I've found the problem!
It was a simple typo in the typedef palpr_recognize_rawimage_type line:
I forgot to add the suffix _type to the type declaration and hence the type and the actual pointer had the same name - which obviously would cause troubles...
If I had looked past to first error from the compiler, I would have spotted the following: note: previous declaration and it would have been obvious that I mesed something up in my type naming.
--> It's worth it to not to only look at the first/top error but also look at least at the second one too - as you never know, it may provide a hint too!
Related
This question already has answers here:
What is the best way to disable implicit conversion from pointer types to bool when constructing an std::variant?
(2 answers)
Why is there an implicit type conversion from pointers to bool in C++?
(3 answers)
Closed 1 year ago.
I'm seeing some odd behavior in regard to passing a pointer into a function that expects a constant reference. Obviously C++ expects me to de reference the pointer before I pass it into the function expecting the reference. I'm looking for an error or warning but I'm not getting one UNLESS a certain condition is met that doesn't make any sense to me.
The type of the pointer and reference is a C++ 17 Standard Variant (below). If my C++17 variant includes the boolean in the template (as below) then GCC8.3 compiles the code just fine. But I have unexpected runtime results.
If I remove the boolean from the standard variant template, then the code does not compile as I expect. Why the difference?
#include <iostream>
#include <variant>
#include <stdint.h>
typedef std::variant <
std::monostate,
int8_t,
int16_t,
int32_t,
int64_t,
uint8_t,
uint16_t,
uint32_t,
uint64_t,
float,
double
,bool //If bool is in the variant, the compiler compiles the code without error and understandably has UB. Why isn't the lack of de-reference bug in DoThing not caught when that is the case?
> StdVARIANT;
//if 'bool' is commented out of the variant the error (expected) is:
//invalid initialization of reference of type ‘const StdVARIANT&’
static size_t GetIndexOfVariant(const StdVARIANT& RefToVariant);
static size_t DoThing(StdVARIANT* PtrToVariant);
static size_t DoThing(StdVARIANT* PtrToVariant){
return GetIndexOfVariant(PtrToVariant); //this is a bug-PtrToVariant should be de referenced!
}
static size_t GetIndexOfVariant(const StdVARIANT& RefToVariant){
size_t Index = RefToVariant.index();
return Index;
}
int main()
{
StdVARIANT* myvar = new StdVARIANT();
*myvar = (int32_t)1;
std::cout<<"long: "<<std::get<int32_t>(*myvar)<<" "<<sizeof(std::get<int32_t>(*myvar))<<std::endl;
*myvar = (double)2;
std::cout<<"double: "<<std::get<double>(*myvar)<<" "<<sizeof(std::get<double>(*myvar))<<std::endl;
std::cout<< myvar->index() << " " << DoThing(myvar)<<std::endl; //when 'bool' is in the std::variant, these two calls return different results (UB)
delete myvar;
return 0;
}
Compile and run as the code block above:
~/gcc-test$ g++ -std=c++17 -Wall -Wextra -pedantic main.cpp
~/gcc-test$ ./a.out
long: 1 4
double: 2 8
10 11
Comment 'bool' out of StdVARIANT, and:
~/gcc-test$ g++ -std=c++17 -Wall -Wextra -pedantic main.cpp
main.cpp: In function ‘size_t DoThing(StdVARIANT*)’:
main.cpp:27:30: error: invalid initialization of reference of type ‘const StdVARIANT&’ {aka ‘const std::variant<std::monostate, signed char, short int, int, long int, unsigned char, short unsigned int, unsigned int, long unsigned int, float, double>&’} from expression of type ‘StdVARIANT*’ {aka ‘std::variant<std::monostate, signed char, short int, int, long int, unsigned char, short unsigned int, unsigned int, long unsigned int, float, double>*’}
return GetIndexOfVariant(PtrToVariant); //this is a bug-PtrToVariant should be de referenced!
^~~~~~~~~~~~
main.cpp:23:15: note: in passing argument 1 of ‘size_t GetIndexOfVariant(const StdVARIANT&)’
static size_t GetIndexOfVariant(const StdVARIANT& RefToVariant);
^~~~~~~~~~~~~~~~~
Why don't I always get the error instead of just when bool is commented out?
To reproduce the problem, you can simplify your code as follows
#include <iostream>
#include <variant>
#include <stdint.h>
typedef std::variant <
std::monostate,
int8_t,
int16_t,
int32_t,
int64_t,
uint8_t,
uint16_t,
uint32_t,
uint64_t,
float,
double
,bool //If bool is in the variant, the compiler compiles the code without error and understandably has UB. Why isn't the lack of de-reference bug in DoThing not caught when that is the case?
> StdVARIANT;
int main()
{
StdVARIANT * pVar = new StdVARIANT();
StdVARIANT var = pVar;
}
The point is that a StdVARIANT * can't be converted to any of the StdVARIANT alternative except for bool.
So if StdVARIANT contains bool,
StdVARIANT var = pVar;
var is initialized as containing a bool value (a true, given that pVar isn't nullptr).
If StdVARIANT doesn't contains bool, the var initialization fails.
The same inside your DoThing() function: when you call
GetIndexOfVariant(PtrToVariant);
a temporary StdVARIANT is created (or not, if bool isn't available) and the constant reference is passed to GetIndexOfVariant().
I am trying to cast TracedValue<uint32_t> m_bytesInFlight to uint32_t but I get the following error
error: cannot convert ‘ns3::TracedValue<ns3::SequenceNumber<unsigned int, int> >’ to ‘uint32_t {aka unsigned int}
Function prototype and variable declarations are
uint32_t UnAckDCount (void) const;
TracedValue<uint32_t> m_bytesInFlight {0}; //!< Bytes in flight
Here i am calling the function
uint32_t
TcpSocketBase::UnAckDCount () const
{
return m_tcb->m_highTxMark - (uint32_t) m_tcb->m_bytesInFlight;
}
Please suggest some method so that I can execute the return statement to get the result. Thanks in advance
Changing m_tcb->m_highTxMark to m_tcb->m_highTxMark.Get().GetValue() should work.
Seeing the compiler error, it's easy to figure out that variable m_highTxMark is of type ns3::TracedValue<ns3::SequenceNumber<unsigned int, int> >. I checked the documentation of ns3::TracedValue and ns3::SequenceNumber, they both have getter functions Get() and GetValue() respectively.
See:
https://www.nsnam.org/doxygen/classns3_1_1_traced_value.html
https://www.nsnam.org/doxygen/classns3_1_1_sequence_number.html
Here's the compiler output:
[brian#brian-arch-laptop Lab1]$ g++ -g -Wall -std=c++11 objectIO.cpp main.cpp -o main
objectIO.cpp:33:14: error: prototype for ‘std::vector<Type> objectIO<Type>::loadObjects(Type, std::string, unsigned int, unsigned int)’ does not match any in class ‘objectIO<Type>’
vector<Type> objectIO<Type>::loadObjects(Type dummyObject,
^
objectIO.h:14:23: error: candidate is: static std::vector<Type> objectIO<Type>::loadObjects(std::string, unsigned int, unsigned int)
static vector<Type> loadObjects(Type dummyObject, string fileName, unsigned numObjects,unsigned numLinesPerObject);
^
from my research, I've discovered that this error typically happens when one has declared a function, but when they define it, it has a different number of arguments or arguments of different types. I've also found that this error normally happens when one declares a function using "const" but then fails to use "const" when defining the function.
Neither of those cases match my situation. I have matching aruments, and I'm not making my functions constant. Here are the lines in question from my source:
From my source (.cpp) file:
template <class Type>
vector<Type> objectIO<Type>::loadObjects(Type dummyObject,
string filename,
unsigned numObjects,
unsigned numLinesPerObject){/*functionality here*/}
From my header (.h) file:
template <class Type>
class objectIO{
public:
static vector<Type> loadObjects(Type dummyObject, string fileName,
unsigned numObjects,
unsigned numLinesPerObject);
}
All definition of a template class shall be placed in one header file.
Your code is missing a semicolon after the class's closing brace:
template <class Type>
class objectIO{
public:
static vector<Type> loadObjects(Type dummyObject, string fileName,
unsigned numObjects,
unsigned numLinesPerObject);
} /* <-- RIGHT HERE */
That usually messes up whatever comes next in the source code, sometimes with a really mistaken error message.
I'm trying to use __m128i as the value type of a cache-aligned vector with GCC, and I'm getting the following error:
/usr/include/tbb/cache_aligned_allocator.h:105:32: error: request for member ‘~tbb::cache_aligned_allocator<__vector(2) long long int>::value_type’ in ‘* p’, which is of non-class type ‘tbb::cache_aligned_allocator<__vector(2) long long int>::value_type {aka __vector(2) long long int}’
The compiler traces it to the following line in tbb/cache_aligned_allocator.h:
void destroy( pointer p ) {p->~value_type();}
Here is the code that triggers the compiler error:
#include <vector>
#include <emmintrin.h>
#include <tbb/cache_aligned_allocator.h>
int main()
{
std::vector<int, tbb::cache_aligned_allocator<int> > success;
std::vector<__m128i, tbb::cache_aligned_allocator<__m128i> > failure;
return 0;
}
According to Debian versioning, my GCC version is 4.6.1-2, and my TBB version is 3.0+r147-1.
Is this a bug in Threading Building Blocks, or am I misusing something?
I think the problem lies with how the __m128 types are implemented in gcc. They are not actual types in the C++ sense, in that they are neither POD (Plain Old Data, like int/double/char/etc.) nor classes. The vector(2) long long int identifier is how gcc refers to the type internally. The error that you showed is from the compiler complaining about not being able to find a destructor for __m128i because it is not a class type.
A workaround for this could involve creating your own type that is 128 bits in size and using a vector of those instead. You could provide a custom cast operator to the __m128i type for convenience if you want, or just cast a pointer to the first element in the vector to a __m128i if you just want to use the vector as a convenient memory allocation mechanism.
The following code does not compile if std::abs(angle) is present. The type of angle is in this case a short int.
template <class T>
typename T::storage_t::single_t FastSin(const typename T::storage_t::double_t &angle) {
const int B = (sizeof(typename T::storage_t::single_t)*8) - 2;
return (angle<<1) - ((angle*(std::abs(angle)))>>B);
}
A close look at the messages can verify that angle is in fact a short int. However, if I am reading the error correctly, GCC turns it into a double.
math.hpp: In function ‘typename T::storage_t::single_t FastSin(const typename T::storage_t::double_t&) [with T = Fixed<_t<signed char, short int> >, typename T::storage_t::single_t = signed char, typename T::storage_t::double_t = short int]’:
vector.hpp:106:30: instantiated from ‘void Vector2<T>::FastRotate(const single_t&) [with T = Fixed<_t<signed char, short int> >, Vector2<T>::single_t = signed char]’
test.cpp:9:18: instantiated from here
math.hpp:11:52: error: invalid operands of types ‘__gnu_cxx::__enable_if<true, double>::__type {aka double}’ and ‘const int’ to binary ‘operator>>’
What is going on here? Even return (angle<<1) - ((angle*(std::abs<int>(angle)))>>B); does the same.
I am using gcc version 4.6.1. The only external headers included are <cmath> and <cstdint>. The compilation flags are -std=c++0x -Wall.
abs() is not a template, but a set of overload functions. According to the standard, the overload for int, long, float, double, long double should exist. But the overload for short does not exist. But as the conversion sequence from short to int is only a promotion, and the conversion sequence form short to the other overloaded types are all conversions, the overload for int should be selected.
But in g++ (version 4.5.2 for me), a non-standard template is added to cmath:
template<typename _Tp>
inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
double>::__type
abs(_Tp __x)
{ return __builtin_fabs(__x); }
This template would take all built-in integral types other than int and long and give a return value of double.
As a matter of fact, using type unsigned int also produces this error in g++:
#include <cstdlib>
#include <cmath>
int main() {
unsigned int i,j;
i=0;
j=std::abs(i)>>2;
return 0;
}
Explicitly casting it to int (std::abs((int)i);) should solve this problem.
The std::abs() function isn't a template in C++; there are just several overloads provided for different types. The ones for the integral types are in the header <cstdlib>. See http://www.cplusplus.com/reference/clibrary/cstdlib/abs/ and http://www.cplusplus.com/reference/clibrary/cmath/abs/ for more info.
I know that this post is already answered long ago, but i just want to give another perspective which should help someone else. My problem was with QT and mingw, always when i build with boost or some other libraries which use cmath and cstdlib i got this error. After some time i was pretty annoyed with this error, and i decided to do a little research about those two files.
I totally agree with fefe and his answer but that can only solve problems if you use it in you program or library ,and you know from a start what is a problem, and that wasn't my problem.
If you really need to include both files in same time (you need system, malloc... and all math functions) quick and dirty fix is to open header and on 106 line (on my computer) you will see something like this:
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
using ::div_t;
using ::ldiv_t;
using ::abort;
//using ::abs;
using ::atexit;
using ::atof;
using ::atoi;
using ::atol;
using ::bsearch;
using ::calloc;
.
.
.
From code above you can see that cstdlib have function abs in std namespace and you need to comment that line in order to enable use of cmath abs function and to get rid of that nasty error.
I hope that this will help someone, and i am sorry for such a long post.