I have a class that has:
private:
uint32_t *data;
and the in one of the functions I'm doing:
void foo() {
data = new uint32_t[size];
}
and that is working fine. Now i wanted to make it a bit more flexible, so i wanted to make foo() a template:
template<typename T>
T foo() {
data = new T[size];
}
and i try to use it:
class.foo<uint64_t>();
But compilation fails saying that:
error: cannot convert 'long long unsigned int*' to 'unsigned int*' in assignment
Is it possible to do something like that? I tried declaring
void *data;
and it compiled, but then I cannot do
sizeof(data[1]);
which is essentially why I need to pass the type.
EDIT:
Thank you for your responses, there are a few thing I'd like to add after looking at your answers.
I'm using raw pointer instead of container because it operates on memory that is used also by external hardware (I'm not running this on PC).
Using this memory is optional for this class, so I don't want to allocate it if its not needed.
I use this class in a few places where I don't need *data at all, so I'd rather avoid making the whole class a template.
Another thought:
Default template type might be a good compromise, is there a way to create a class that I won't have to later use that way:
Class<> my;
but still:
Class my;
and if needed:
Class<type> my;
?
Rather than converting your function to a template, convert your class to a template:
template <class T>
class myclass {
private:
T *data;
public:
myclass(size_t size) : data(new T[size]) {
}
... // Add copy constructor, assignment operator, and a destructor
// to properly manage the pointer. See "rule of three" for more info.
};
This way the type of array element becomes part of the type of your class, letting your member functions work with the data without any additional type casting.
Note that using raw array pointer in the class comes with significant liabilities in terms of memory management. You would be better off with std::vector<T>.
You may consider making your whole class a template, like this:
template <typename T>
class Foo
{
private:
T *data;
public:
Foo(size_t size_):
data{new T[size]}
{
}
~Foo()
{
delete[] data;
}
};
Implementation is here only partial. See this about rule of 3, 5, 0.
Or using managed pointers:
template <typename T>
class Foo
{
private:
std::unique_ptr<T[]> data;
size_t size;
public:
Foo(size_t size_):
data{std::make_unique<T[]>(size_)},
size(size_)
{
}
~Foo()
{
// no need to call delete, unique_ptr will do it
}
};
But once you're here, depending on your use case, alternatives may be preferable, like std::vector:
std::vector<uint64_t> v(size);
// ...
std::cout << v.size() << std::endl;
EDIT:
From the additional information you provided, it looks like the following design may better suit your needs:
class Base
{
public:
virtual void* get_data() {
return nullptr;
}
virtual size_t get_size() {
return 0;
}
};
template<typename T>
class Foo : public Base
{
private:
T* data;
size_t size;
public:
Foo(size_t size_):
data{new T[size_]},
size(size_) {}
~Foo() {
delete[] this->data; // same remark as above about rule of 5
}
virtual void* get_data() overriden {
return this->data;
}
virtual size_t get_size() overriden {
return this->size;
}
};
With the following usage:
std::unique_ptr<Base> my_without_data =
std::make_unique<Base>();
std::unique_ptr<Base> my_with_data =
std::make_unique<Foo<type>>(size);
Note that in the second call, std::make_unique returns a unique_ptr<Foo<type>> with an appropriate deleter calling Foo<type>'s destructor. The deleter will be copied when assigning to my_with_data and call Foo<type>'s destructor even if Base's destructor is not declared virtual.
I chose here a design with virtual methods in Base to access data. Depending on your real use case, other ways may be used.
Convert your whole class to a templated class
template<typename T>
class Container {
public:
Container() :
data(NULL)
{}
~Container() {
if (data) {
delete [] data;
}
}
T* foo(int size) {
if (data) {
delete [] data;
}
data = new T[size];
return data;
}
private:
T *data;
};
Related
consider this layout:
#include <memory>
#include <vector>
struct data{};
struct task {
data* data_ptr = nullptr;
virtual void work() = 0;
};
struct special_task : task {
void work() override { /*work with the data*/ }
};
a task has access to data. The derived classes must implement their indivial work() routine.
Now task_collection stores the data and a vector of task pointers, and instances of derived classes can be added to that vector:
struct task_collection {
data data;
std::vector<std::unique_ptr<task>> tasks;
template<typename T>
void add() {
this->tasks.push_back(std::make_unique<T>());
this->tasks.back()->data_ptr = &this->data;
}
};
int main() {
task_collection t;
t.add<special_task>();
}
now this works very well. However, I am wondering if I can replace the data* data_ptr with a reference as it seems more appropriate here and it also replaces the many -> with .s
However, it seems impossible to implement this without changing the layout of special_task as the reference requires a constructor in the base task class and derived classes dismiss their base constructors:
struct task {
task(data& data) : data_ref(data){}
data& data_ref;
virtual void work() = 0;
};
struct special_task : task {
void work() override { /*work with the data*/ }
};
struct task_collection {
data data;
std::vector<std::unique_ptr<task>> tasks;
template<typename T>
void add() {
this->tasks.push_back(std::make_unique<T>(this->data)); //Error!
}
};
It gives this error:
Error C2664 'special_task::special_task(const special_task &)': cannot convert argument 1 from 'data' to 'const special_task &'
I am aware that this can be "solved" by adding
using task::task;
to every derived class, as now it now finds the appropriate constructor. This is not really a solution though, as there are hundreds of derived classes potentially, written by multiple people. If one instance of using task::task; is missing it could cause headaches. The additional lines of code also negate the benefit that comes from using reference instead of pointers.
So is there any way to implement task::data_ref as a reference where only task_collection or task are modified, but not any of the derived classes?
ITNOA
If owner of question can accept some of time using get() instead of . to access to the data, he can use std::reference_wrapper instead of raw reference to resolve rebinding problem.
#include <memory>
#include <vector>
#include <functional>
struct data{};
static data empty_data;
struct task {
std::reference_wrapper<data> data_ptr = empty_data;
virtual void work() = 0;
};
struct special_task : task {
void work() override { /*work with the data*/ }
};
struct task_collection {
data data;
std::vector<std::unique_ptr<task>> tasks;
template<typename T>
void add() {
this->tasks.push_back(std::make_unique<T>());
this->tasks.back()->data_ptr = std::ref(this->data);
}
};
int main()
{
task_collection t;
t.add<special_task>();
}
For using the data, you can for example behave like below
data temp_data = t.tasks.back()->data_ptr;
As you can see in How to correctly use std::reference_wrappers, Class std::reference_wrapper implements an implicit converting operator to T&:
constexpr operator T& () const noexcept;
So the implicit operator is called when a T (or T&) is required, and you do not need using get() function, For instance
void f(some_type x);
// ...
std::reference_wrapper<some_type> x;
some_type y = x; // the implicit operator is called
f(x); // the implicit operator is called and the result goes to f.
So you have to sometimes to using .get(). instead of always using ->
I'm reading a lot of questions (and answers) about function pointers, functors and callbacks but I still have a confusion about which is the right tool for me.
Some of them cannot apply to my scenario because it seems my compiler avr-gcc v5.4.0 does not have C++ standard library (i.e. std::function is not available).
This is my base class:
class Debouncer
{
public:
typedef uint8_t (Debouncer::*debouncer_raw_t) (void);
Debouncer() {}
void setRawFunction(Debouncer::debouncer_raw_t callback) { _raw = callback; }
private:
debouncer_raw_t _raw;
void anotherFunction()
{
uint8_t value = _raw();
// do something
}
}
In my other classes I have:
class Inputs
{
public:
Inputs()
{
_deb.setRawFunction(myRaw);
}
private:
Debouncer _deb;
uint8_t myRaw()
{
return something;
}
}
Of course this won't compile because myRaw is not static.
Anyway, I'm going to try to avoid this because it would break the existing code.
If I'm not wrong, a lot of questions seem to ask the other way around.
Instead I just want to pass the pointer of my member function to my Debouncer class, so it can call _raw() when it needs to.
Here I found this advise to avoid std:: library:
#define CALL_MEMBER_FN(object, ptrToMember) ((object).*(ptrToMember))
void userCode(Fred& fred, FredMemFn p) // Use a typedef for pointer-to-member types
{
int ans = CALL_MEMBER_FN(fred,p)('x', 3.14);
// Would normally be: int ans = (fred.*p)('x', 3.14);
// ...
}
But it seems the other way around. Here the class Fred is my Debouncer.
I don't want to call the Debouncer member, but member of the caller class (i.e. Input::myRaw()).
Would you please help me to understand which is the right tool to achieve such a simple task?
Making a member function virtual is a relatively low-overhead way to have a single pointer (to an object) refer to both the object's data and the correct member function.
class InputsBase
{
// All classes that implement myRaw() should inherit from this class
public:
virtual uint8_t myRaw() = 0;
};
class Inputs : public InputsBase
{
public:
Inputs()
{
_deb.setRawFunction(this);
}
private:
Debouncer _deb;
virtual uint8_t myRaw()
{
return something;
}
}
Your Debouncer can then simply store a pointer to the object in question.
class Debouncer
{
public:
typedef InputsBase* debouncer_raw_t;
Debouncer() {}
void setRawFunction(debouncer_raw_t callback) { _raw = callback; }
private:
debouncer_raw_t _raw;
void anotherFunction()
{
uint8_t value = _raw->myRaw();
// do something
}
}
If you know (or require) each of the classes using Debouncer have a public myRaw() function (or better operator(), or actually anything else), the problem is simpler:
template <typename T>
class Debouncer
{
public:
Debouncer (T* t): _t(t) {}
void anotherFunction()
{
uint8_t value = _t->myRaw();
std::cout << static_cast<int>(value);
}
private:
T* _t;
};
class Inputs
{
public:
Inputs() : _deb(this)
{
// beware, if Debouncer uses its parameter in constructor (like call a method),
// you cannot use initializer list
}
uint8_t myRaw()
{
return 13;
}
void foo()
{
_deb.anotherFunction();
}
private:
Debouncer<Inputs> _deb;
};
int main()
{
Inputs i;
i.foo();
}
This would be preferred solution in C++. See for example standard library <algorithm> - any function taking a predicate or some other callable expects to call it with operator() rathen than having to deal with pointers-to-member-function.
If you don't know what function should be called and you really cannot impose any requirement on the classes, you need to store both a pointer (or reference) to the class and a pointer to the member function. Note that you cannot connect pointers to member functions of different classes, so we need templates once again:
template <typename T, typename Func>
class Debouncer
{
public:
Debouncer (T* t, Func f): _t(t), _f(f) {}
void anotherFunction()
{
uint8_t value = (_t->*_f)(); //I get it now why isocpp asks to use macro here, the syntax is horrible
std::cout << static_cast<int>(value);
}
private:
T* _t;
Func _f;
};
class Inputs
{
public:
Inputs() : _deb(this, &Inputs::myRaw)
{
// beware, if Debouncer uses its parameter in constructor (like call a method),
// you cannot use initializer list
}
uint8_t myRaw()
{
return 13;
}
void foo()
{
_deb.anotherFunction();
}
private:
Debouncer<Inputs, decltype(&Inputs::myRaw)> _deb; //decltype is C++11, you could also declare type like you did in your question
};
int main()
{
Inputs i;
i.foo();
}
I have this CRTP:
template <class T>
struct S {
void clear() { new (this) T; }
};
class SS : public S<SS> {
int i = 5;
};
int main() {
SS s;
s.clear();
}
Is clear() guaranteed to work as expected? Does it even matter if S is virtual or not?
For the matter we can assume all the classes inheriting S won't have anything but primitive or POD types, so no fancy constructors and destructors.
I compiled with gcc and valgrind didn't seem to complain but it feels weird.
To recreate the child type at the right place in memory you'll have to cast the this pointer.
Also, if you do not call the destructor, you have to assert that the type is trivially destructible:
template <class T>
struct S {
void clear() {
static_assert(std::is_base_of_v<S, T>);
static_assert(std::is_trivially_destructible_v<T>);
new (static_cast<T*>(this)) T;
}
};
Valgrind did not warn about anything since the this from the base was the same as the derived class, you did not overwrite any memory past what was allocated.
Beyond the static_cast<T*>(this), I also suggest to call dtor on the object first.
template <class T>
struct S {
void clear() {
auto this_ptr = static_cast<T*>(this)
this_ptr->~T();
new (this_ptr) T();
}
};
My c++ code has to work with an underlying c-library. I have a c++ object that looks somewhat like this:
template <typename T>
class MyClass
{
public:
explicit MyClass(int x)
: mVar(x)
{
}
private:
int mVar;
};
Later in my c++ code I do the following:
auto p = new MyClass<int>(10);
call_c_lib_function((void*) p);
The c function saves the pointer 'p' in a larger c-structure. Later when the large
c object is getting destroyed, it invokes the delete handler.
void
c_delete_handler(void* data)
{
// data is holding the pointer value 'p' from above.
}
Since the object is getting destroyed, I need to free the object that allocated.
Per the c++ spec, 'delete void_ptr' is undefined since it doesn't know how to
invoke the appropriate destructor. How do I invoke delete on the appropriate
template object?
One solution I could think of was to create a wrapper structure around my MyClass pointer.
struct Wrapper {
enum template_type {
template_int,
template_double,
template_string,
...
};
int template_type;
void* obj_ptr;
};
before callign the call_c_lib_function, I'd do the following:
auto p = new MyClass<int>(10);
auto w = new Wrapper()
w.template_type = Wrapper::template_int;
w.obj_ptr = (void*) p;
call_c_lib_function((void) w);
and now in the delete handler, I can do the following:
void
c_delete_handler(void* data)
{
Wrapper* w = (Wrapper*) data;
switch (w->template_type) {
case Wrapper::template_int:
delete (MyClass<int>*) w->obj_ptr;
break;
case Wrapper::template_double:
delete (MyClass<double>*) w->obj_ptr;
break;
...
}
}
Is this a correct approach? is there a better alternative?
Would appreciate any inputs. Thanks.
Instead of using Wrapper, use a base class, if that's an option.
class MyBase
{
public:
virtual ~MyBase() {};
};
template <typename T>
class MyClass : public MyBase
{
public:
explicit MyClass(int x) : mVar(x) {}
private:
int mVar;
};
and then
void c_delete_handler(void* data)
{
Base* basePtr = reinterpret_cast<Base*>(data);
delete basePtr;
}
This approach obviates the need for keeping track of whether MyClass was instantiated using int, double, std::string, or ....
Suppose I have two classes...
We can call the first FooReader and it looks something like this:
class FooReader {
public:
FooReader(const Foo* const foo)
: m_foo(foo) {
}
FooData readFooDataAndAdvance() {
// the point here is that the algorithm is stateful
// and relies upon the m_offset member
return m_foo[m_offset++];
}
private:
const Foo* const m_foo;
size_t m_offset = 0; // used in readFooDataAndAdvance
};
We can call the second FooWriter and it looks something like this:
class FooWriter {
public:
FooWriter(Foo* const foo)
: m_foo(foo) {
}
void writeFooDataAndAdvance(const FooData& foodata) {
// the point here is that the algorithm is stateful
// and relies upon the m_offset member
m_foo[m_offset++] = foodata;
}
private:
Foo* const m_foo;
size_t m_offset = 0;
};
These both work wonderfully and do their job as intended. Now suppose I want to create a FooReaderWriter class. Note that the
I naturally want to say that this new class "is a" FooReader and "is a" FooWriter; the interface is simply the amalgamation of the two classes and the semantics remain the same. I don't want to reimplement perfectly good member functions.
One could model this relationship using inheritance like so:
class FooReaderWriter : public FooReader, public FooWriter { };
This is nice because I get the shared interface, I get the implementation and I nicely model the relationship between the classes. However there are problems:
The Foo* member is duplicated in the base classes. This is a waste of memory.
The m_offset member is separate for each base type, but they need to share it (i.e. calling either readFooDataAndAdvance and writeFooDataAndAdvance should advance the same m_offset member).
I can't use the PIMPL pattern and store m_foo and m_offset in there, because I'd lose the const-ness of the m_foo pointer in the base FooReader class.
Is there anything else I can do to resolve these issues, without reimplementing the functionality contained within those classes?
This seems ready made for the mixin pattern. We have our most base class which just declares the members:
template <class T>
class members {
public:
members(T* f) : m_foo(f) { }
protected:
T* const m_foo;
size_t m_offset = 0;
};
and then we write some wrappers around it to add reading:
template <class T>
struct reader : T {
using T::T;
Foo readAndAdvance() {
return this->m_foo[this->m_offset++];
};
};
and writing:
template <class T>
struct writer : T {
using T::T;
void writeAndAdvance(Foo const& f) {
this->m_foo[this->m_offset++] = f;
}
};
and then you just use those as appropriate:
using FooReader = reader<members<Foo const>>;
using FooWriter = writer<members<Foo>>;
using FooReaderWriter = writer<reader<members<Foo>>>;
CRTP.
template<class Storage>
class FooReaderImpl {
public:
FooData readFooDataAndAdvance() {
// the point here is that the algorithm is stateful
// and relies upon the m_offset member
return get_storage()->m_foo[get_storage()->m_offset++];
}
private:
Storage const* get_storage() const { return static_cast<Storage const*>(this); }
Storage * get_storage() { return static_cast<Storage*>(this); }
};
template<class Storage>
class FooWriterImpl {
public:
void writeFooDataAndAdvance(const FooData& foodata) {
// the point here is that the algorithm is stateful
// and relies upon the m_offset member
get_storage()->m_foo[get_storage()->m_offset++] = foodata;
}
private:
Storage const* get_storage() const { return static_cast<Storage const*>(this); }
Storage * get_storage() { return static_cast<Storage*>(this); }
};
template<class T>
struct storage_with_offset {
T* m_foo = nullptr;
std::size_t m_offset = 0;
};
struct FooReader:
FooReaderImpl<FooReader>,
storage_with_offset<const Foo>
{
FooReader(Foo const* p):
storage_with_offset<const Foo>{p}
{}
};
struct FooWriter:
FooWriterImpl<FooWriter>,
storage_with_offset<Foo>
{
FooWriter(Foo* p):
storage_with_offset<Foo>{p}
{}
};
struct FooReaderWriter:
FooWriterImpl<FooReaderWriter>,
FooReaderImpl<FooReaderWriter>,
storage_with_offset<Foo>
{
FooReaderWriter(Foo const* p):
storage_with_offset<Foo>{p}
{}
};
If you need an abstract interface for runtime polymorphism, inherit FooReaderImpl and FooWriterImpl from them.
Now, FooReaderWriter obeys the ducktype contract of FooReader and FooWriter. So if you use type erasure instead of inheritance, it will qualify for either (at point of use).
I'd be tempted to change them to
using FooReader = std::function<FooData()>;
using FooWriter = std::function<void(FooData const&)>;
and then implement a multi-signature std::function for FooReaderWriter. But I'm strange and a bit unhinged that way.