is possible to re-map STL class object from void* ?
#include <string>
void func(void *d)
{
std::string &s = reinterpret_cast<std::string&>(d);
}
int main()
{
std::string s = "Hi";
func(reinterpret_cast<void*>(&s));
}
Use static_cast to convert void pointers back to other pointers, just be sure to convert back to the exact same type used originally. No cast is necessary to convert to a void pointer.
This works for any pointer type, including pointers to types from the stdlib. (Technically any pointer to object type, but this is what is meant by "pointers"; other types of pointers, such as pointers to data members, require qualification.)
void func(void *d) {
std::string &s = *static_cast<std::string*>(d);
// It is more common to make s a pointer too, but I kept the reference
// that you have.
}
int main() {
std::string s = "Hi";
func(&s);
return 0;
}
I re-wrote as following,
#include<string>
void func(void *d)
{
std::string *x = static_cast<std::string*>(d);
/* since, d is pointer to address, it should be casted back to pointer
Note: no reinterpretation is required when casting from void* */
}
int main()
{
std::string s = "Hi";
func(&s); //implicit converssion, no cast required
}
You code shouldn't compile.
Change
std::string &s = reinterpret_cast<std::string&>(d);
to
std::string *s = static_cast<std::string*>(d);
EDIT:
Updated code. Use static_cast instead of reinterpret_cast
Yes, it is possible, but you are trying to cast from a pointer to void *, then to a reference. The reinterpret_cast operator only allows casting back to exactly the same type that you started with. Try this instead:
void func(void *d)
{
std::string &s = *reinterpret_cast<std::string*>(d);
}
Related
There is a function which takes void*
After passing my vector<char*>, how do I cast it back to vector<char*> and print its content using casting in C++?
Example:
void testFunction(void* data){
//cast data back to vector<char *> and print its content
}
int main()
{
std::vector<char *> arg(1);
std::string someString = "testString";
arg[0] = (char *)someString.c_str();
testFunction(&arg);
return 0;
}
You can use a static_cast to cast a void* pointer to almost any other type of pointer. The following code works for me:
void testFunction(void* data)
{
std::vector<char*>* vecdata = static_cast<std::vector<char*>*>(data);
for (auto c : *vecdata) std::cout << c;
std::cout << std::endl;
}
Just use reinterpret_cast
vector<char*>* parg = reinterpret_cast<vector<char*>*>(data);
char* mystr = parg->at(0);
std::vector<char*>& myVec= *reinterpret_cast<std::vector<char*>*>(data);
std::cout<<myVec[0];
Well actually this worked.
I'm creating a class were doing something with an array of struct, but the problem is I cannot assign array reference to the object.
already trying to find the solution, but only works with copying the entire array to the object variable with memcpy, how to do this differently without copying the array?
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define arrayLength(array) (size_t)((sizeof array) / (sizeof array[0]))
typedef struct someStruct {
int id;
char *name;
} someStruct;
class someClass {
private:
someStruct *list;
public:
someClass(someStruct const *const listData) { list = listData; }
};
int main() {
someStruct list[255] = {
{1, "one"},
};
someClass object(list);
return 0;
}
error: invalid conversion from 'const someStruct*' to 'someStruct*' [-fpermissive]
someClass(someStruct const *const listData) { list = listData; }
You are supplying a const pointer, then assigning a non-const pointer to that const pointer. The compiler is not letting you downgrade const to non-const.
Make someClass's list a const pointer, or remove the const qualifiers from the initializer parameters.
if you are not sure about compiler error message,
here it is in short:
in constructor body you have tried to assign pointer to const value to pointer to value, implicates that if compiler let you, you will try to change const value using pointer and for that you certainly can't use pointer to const. At least not without any special purpose casting.
This is not the only thing in your code sample that should be changed, but you can start from there.
I have a simple class with one attribute std::unique_ptr<unsigned char[]> in C++. I want to have a function that converts string to std::unique_ptr<unsigned char[]>, other to convert float to std::unique_ptr<unsigned char[]>, and a third to return the attribute std::unique_ptr<unsigned char[]>. My header is compiling but the source CPP is not. Even the return attribute is not compiling.
#include <memory>
class SkinnyBuffer {
private:
std::unique_ptr<unsigned char[]> _buff;
public:
~SkinnyBuffer();
SkinnyBuffer();
void setBuffValue(float f);
void setBuffValue(std::string str);
std::unique_ptr<unsigned char[]>* getBuffValue();
};
#include "utils/SkinnyBuffer.h"
SkinnyBuffer::~SkinnyBuffer() { }
SkinnyBuffer::SkinnyBuffer() { }
void SkinnyBuffer::setBuffValue(float f) {
// How to implement it
_buff = f;
}
void SkinnyBuffer::setBuffValue(std::string str) {
_buff = std::unique_ptr<unsigned char[]>(str.data(), str.data() + str.length());
}
std::unique_ptr<unsigned char[]>* SkinnyBuffer::getBuffValue() {
return &_buff;
}
std::unique_ptr is a non-copyable object. If you need a read-only access to it, you have two (main) options:
Return a reference to unique_ptr itself:
const std::unique_ptr<unsigned char[]>& getBuffValue() const
{
return _buff;
}
Return a const pointer to the managed array:
const unsigned char* getBuffValue() const
{
return _buff.get();
}
To assign a string to the buffer, you can do:
void setBuffValue(const std::string& str)
{
_buff = std::make_unique<unsigned char []>(str.length() + 1);
std::copy_n(str.c_str(), str.length() + 1, _buff.get());
}
Note that you have to copy the terminating null character to your buffer. Otherwise it will be almost useless for the outside world because its length will not be known to the user.
But do you really need std::unique_ptr<unsigned char[]>? std::vector seems to be more appropriate here.
You cannot do it this way. You have to copy the content of the string in a new array that is pointed by the unique pointer and then return the unique pointer.
The other option is to return a string in your two inherited classes.
Return a view of the data in buff_, don't try to copy it.
const unsigned char * SkinnyBuffer::getBuffValue() const {
return _buff.get();
}
You can use that value until the SkinnyBuffer is destroyed or modified.
First off I would like to mention that this works with MSVC but not with clang. I am using Clang with c++11.
I have a function pointer:
typedef void (*Log) (const char* title, const char* msg, const char* file, int line);
I have this struct:
struct FunctionList
{
protected:
static const int kNbrMax = 32;
FunctionList();
bool Add(const void* f);
bool Remove(const void* f);
const void* m_functions[kNbrMax];
};
And this class:
template<typename T>
struct MessageFunctionList
: public FunctionList
{
public:
MessageFunctionList(T defaultFunction)
{
Add(defaultFunction);
}
void Call(const char* title,const char* cause,const char* file,int line)
{
for (unsigned long i = 0;i < m_nbrUsed;++i)
{
reinterpret_cast<T>(m_functions[i])(title,cause,file,line);
}
}
}
I am creating it like so:
static void DefaultLogMessageFunction(const char* title,const char* msg,const char* file,int line)
{
}
MessageFunctionList<Log> functionList(DefaultLogMessageFunction)
But I get the compile time error:
reinterpret_cast from 'const void ' to 'void ()(const char *, const
char *, const char *, int)' casts away qualifiers for line:
reinterpret_cast(m_functions[i])(title,cause,file,line);
So as far as I understand I am trying to cast my const list of functions to a non const value. That is not allowed which makes sense. So I tried the following:
const void* funcPtr = m_functions[i];
const T call = reinterpret_cast<const T>(funcPtr);
call(title, cause, file, line);
But that does not work either.
This works:
void* funcPtr = const_cast<void*>(m_functions[i]);
T call = reinterpret_cast<T>(funcPtr);
call(title,cause,file,line);
But I would like to avoid using a const cast. What am I doing wrong? How can I call this const function? Or is it simply not allowed because it does not know if the function being called is a const function or not? Or perhaps it is because my static function is not a member of a class so it can not be declared const?
You are storing the function pointers as const void*:
const void* m_functions[kNbrMax];
And you are trying to cast them to T and call it using reinterpret_cast:
reinterpret_cast<T>(m_functions[i])(title,cause,file,line);
However, reinterpret_cast cannot remove const qualifier from a type, therefore, you should first remove the const using const_cast:
reinterpret_cast<T>(const_cast<void*>(m_functions[i]))(title,cause,file,line);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
However, please note that const_cast engenders undefined behavior and is unsafe. So is calling a function pointer returned from reinterpret_cast if the original pointer was not actually a T.
Edit:
You can call a const qualified function pointer, however, then the reinterpret_cast should contain the const qualifier:
reinterpret_cast<const T>(m_functions[i])(title,cause,file,line);
I have some problem removing constness using const_cast. Error msg says "Conversion is a valid standard conversion....."
What is the nature of this problem? Why should I use C-style cast instead?
"error C2440: 'const_cast' : cannot convert from 'const size_t' to 'size_t'"
"Conversion is a valid standard conversion, which can be performed implicitly or by use of static_cast, C-style cast or function-style cast"
template<typename T>
const IFixedMemory* FixedMemoryPkt<T>::operator=(const IFixedMemory* srcObj)
{
// doesn't remove constness this way. why?
const_cast<char*> (this->m_Address) = (char*)srcObj->GetAddress();
// compile this way, but maybe(?) undefined behaviour
// const_cast<char*&> (this->m_Address) = (char*)srcObj->GetAddress();
// doesn't doesn't work too
const_cast<size_t> (this->m_Size) = (size_t)(srcObj->GetSize());
// const_cast<size_t> (this->m_Size) = 0;
return this;
}
template<typename T>
class FixedMemoryPkt : public IFixedMemory
{
private:
const size_t m_Size;
const char* m_Address;
}
class IFixedMemory
{
public:
virtual const char* GetAddress() const = 0;
virtual size_t GetSize() const = 0;
}
const_cast is used to convert from pointers or references to const objects, to their non-const equivalents. However, you can't use them to modify the object they refer to if the object itself is const. There is no valid way to modify m_Size; if you want to modify it, then don't declare it const.
You do not need a cast to assign to the pointer, since the pointer itself is not const:
this->m_Memory = srcObj->GetAddress();
If you did want the pointer itself to be const, then the const would come after the *:
char * const m_Address;
and, as with the const size_t, you wouldn't be able to reassign it.
As the error says, you can convert a const value into a non-const temporary copy of that value without a cast; but you couldn't assign to that temporary.
You're attempting to cast the size_t thing to an r-value, and you can't assign to an r-value.
I have to say that casting away the constness of your size_t member is pretty evil. That's what mutable is for. And AFAICS your 1st const cast does nothing useful.
Works this way now...
template<typename T>
const IFixedMemory* FixedMemoryPkt<T>::operator=(const IFixedMemory* srcObj)
{
this->m_Address = srcObj->GetAddress();
this->m_Size = srcObj->GetSize();
return this;
}
template<typename T>
class FixedMemoryPkt : public IFixedMemory
{
private:
const char* m_Address;
size_t m_Size;
};