I have an abstract base class that can't use STL containers and is limited to POD types:
class IBase
{
public:
virtual ~IBase() = default;
virtual void getName( char*& ) = 0;
}
I also derive from this class and have helper functions so I can work with my class internally with STL containers:
class Derived : public IBase
{
public:
virtual void getName( char*& );
virtual void getName( std::string& );
private:
std::string name;
}
And implement them as such:
void Derived::getName( char*& name ) // Function signature can't change.
{
name = (char*)malloc( sizeof( char ) * ( m_name.length() + 1 ) );
strcpy( name, m_name.c_str() );
}
void Derived::getName( std::string& name )
{
name = m_name;
}
And I'm handling it like this:
void functionThatDealsWithAbstract( Base* base )
{
char* name;
base->getName( name );
// Do some stuff with c string
free( name ); // Been pointed out that if I am freeing in this space, I should malloc in this space as well (because of module boundaries)
}
But I'm wondering if there is a more safe way to handle this with C++11. I don't want accidentally copy/paste and forget that I need to free the pointer. I came up with this:
void functionThatDealsWithAbstract( Base* base )
{
char* namePointer;
base->getName( namePointer );
std::shared_ptr<char[]> name( namePointer, std::default_delete<char[]>() );
}
Is this a safe way to deal with C strings using C++11 idioms?
Related
First of all, there's no such built in concept as "interface". By interface in C++, I really mean some abstract base class that looks like:
struct ITreeNode
{
... // some pure virtual functions
};
Then we can have concrete structs that implement the interface, such as:
struct BinaryTreeNode : public ITreeNode
{
BinaryTreeNode* LeftChild;
BinaryTreeNode* RightChild;
// plus the overriden functions
};
It makes good sense: ITreeNode is an interface; not every implementation has Left & Right children - only BinaryTreeNode does.
To make things widely reusable, I want to write a template. So the ITreeNode needs to be ITreeNode<T>, and BinaryTreeNode needs to be BinaryTreeNode<T>, like this:
template<typename T>
struct BinaryTreeNode : public ITreeNode<T>
{
};
To make things even better, let's use unique pointer(smart point is more common, but I know the solution - dynamic_pointer_cast).
template<typename T>
struct BinaryTreeNode : public ITreeNode<T>
{
typedef std::shared_ptr<BinaryTreeNode<T>> SharedPtr;
typedef std::unique_ptr<BinaryTreeNode<T>> UniquePtr;
// ... other stuff
};
Likewise,
template<typename T>
struct ITreeNode
{
typedef std::shared_ptr<ITreeNode<T>> SharedPtr;
typedef std::unique_ptr<ITreeNode<T>> UniquePtr;
};
It's all good, until this point:
Let's assume now we need to write a class BinaryTree.
There's a function insert that takes a value T and insert it into the root node using some algorithm(naturally it will be recursive).
In order to make the function testable, mockable and follow good practice, the arguments need to be interface, rather than concrete classes. (Let's say this is a rigid rule that cannot be broken.)
template<typename T>
void BinaryTree<T>::Insert(const T& value, typename ITreeNode<T>::UniquePtr& ptr)
{
Insert(value, ptr->Left); // Boooooom, exploded
// ...
}
Here's the problem:
Left is not a field of ITreeNode! And worst of all, you cannot cast a unique_ptr<Base> to unique_ptr<Derived>!
What's the best practice for a scenario like this?
Thanks a lot!
Ok, over-engineering it is! But note that, for the most part, such low level data structures benefit HUGELY from transparency and simple memory layouts. Placing the level of abstraction above the container can give significant performance boosts.
template<class T>
struct ITreeNode {
virtual void insert( T const & ) = 0;
virtual void insert( T && ) = 0;
virtual T const* get() const = 0;
virtual T * get() = 0;
// etc
virtual ~ITreeNode() {}
};
template<class T>
struct IBinaryTreeNode : ITreeNode<T> {
virtual IBinaryTreeNode<T> const* left() const = 0;
virtual IBinaryTreeNode<T> const* right() const = 0;
virtual std::unique_ptr<IBinaryTreeNode<T>>& left() = 0;
virtual std::unique_ptr<IBinaryTreeNode<T>>& right() = 0;
virtual void replace(T const &) = 0;
virtual void replace(T &&) = 0;
};
template<class T>
struct BinaryTreeNode : IBinaryTreeNode<T> {
// can be replaced to mock child creation:
std::function<std::unique_ptr<IBinaryTreeNode<T>>()> factory
= {[]{return std::make_unique<BinaryTreeNode<T>>();} };
// left and right kids:
std::unique_ptr<IBinaryTreeNode<T>> pleft;
std::unique_ptr<IBinaryTreeNode<T>> pright;
// data. I'm allowing it to be empty:
std::unique_ptr<T> data;
template<class U>
void insert_helper( U&& t ) {
if (!get()) {
replace(std::forward<U>(t));
} else if (t < *get()) {
if (!left()) left() = factory();
assert(left());
left()->insert(std::forward<U>(t));
} else {
if (!right()) right() = factory();
assert(right());
right()->insert(std::forward<U>(t));
}
}
// not final methods, allowing for balancing:
virtual void insert( T const&t ) override { // NOT final
return insert_helper(t);
}
virtual void insert( T &&t ) override { // NOT final
return insert_helper(std::move(t));
}
// can be empty, so returns pointers not references:
T const* get() const override final {
return data.get();
}
T * get() override final {
return data.get();
}
// short, could probably skip:
template<class U>
void replace_helper( U&& t ) {
data = std::make_unique<T>(std::forward<U>(t));
}
// only left as customization points if you want.
// could do this directly:
virtual void replace(T const & t) override final {
replace_helper(t);
}
virtual void replace(T && t) override final {
replace_helper(std::move(t));
}
// Returns pointers, because no business how we store it in a const
// object:
virtual IBinaryTreeNode<T> const* left() const final override {
return pleft.get();
}
virtual IBinaryTreeNode<T> const* right() const final override {
return pright.get();
}
// returns references to storage, because can be replaced:
// (could implement as getter/setter, but IBinaryTreeNode<T> is
// "almost" an implementation class, some leaking is ok)
virtual std::unique_ptr<IBinaryTreeNode<T>>& left() final override {
return pleft;
}
virtual std::unique_ptr<IBinaryTreeNode<T>>& right() final override {
return pright;
}
};
I have a Visual Studio 2013 C++11 project where I'm trying to define an iterator. I want that iterator to dereference to an object, but internally it actually iterates over some internal data the object requires for construction.
class my_obj
{
public:
my_obj(some_internal_initialization_value_ v);
std::wstring friendly_name() const;
// ...
};
class my_iterator
: public boost::iterator_facade<
my_iterator,
my_obj,
boost::forward_traversal_tag>
{
// ...
private:
my_obj& dereference() const
{
// warning C4172: returning address of local variable or temporary
return my_obj(some_internal_initialization_value_);
}
};
int main( int argc, char* argv[])
{
my_container c;
for (auto o = c.begin(); o != c.end(); ++o)
printf( "%s\n", o->friendly_name().c_str() );
}
These internal values are unimportant implementation details to the user and I'd prefer not to expose them. How can I write the iterator that does this correctly? The alternative is that I would have to do something like this:
my_container c;
for (auto i = c.begin(); i != c.end(); ++i)
{
my_obj o(*i);
printf( "%s\n", o.friendly_name().c_str() );
}
From the boost page on iterator_facade, the template arguments are: derived iterator, value_type, category, reference type, difference_type. Ergo, merely tell it that references are not references
class my_iterator
: public boost::iterator_facade<
my_iterator,
my_obj,
boost::forward_traversal_tag,
my_obj> //dereference returns "my_obj" not "my_obj&"
See it working here: http://coliru.stacked-crooked.com/a/4b09ddc37068368b
I am designing a class in C++/CLR that uses a callback function provided by user code.
This works very nicely if the callback function is free ( i.e. not the member of a class ). It is almost the same as in pure C++.
Here is some sample code that works well:
ref class ClassThatUsesCallback
{
public:
typedef void (*callback_t)( String^ );
void setCallback( callback_t pfun )
{
myCallback = pfun;
}
void Run()
{
if( myCallback != nullptr ) {
myCallback("This is a test");
}
}
private:
callback_t myCallback;
};
void FreeFunction( String^ s )
{
Console::WriteLine( "Free Function Callback " + s );
}
int main(array<System::String ^> ^args)
{
ClassThatUsesCallback^ theClassThatUsesCallback
= gcnew ClassThatUsesCallback();
theClassThatUsesCallback->setCallback( FreeFunction );
theClassThatUsesCallback->Run();
}
However, I would like the callbacked function to be a member of a class in the user code ( so it can make use of and change the attributes of the user code class )
The following code does not compile
ref class ClassThatProvidesCallback
{
public:
void MemberFunction( String^ s )
{
Console::WriteLine( "Member Function Callback " + s );
}
void Run()
{
ClassThatUsesCallback^ theClassThatUsesCallback
= gcnew ClassThatUsesCallback();
theClassThatUsesCallback->setCallback(
&ClassThatProvidesCallback::MemberFunction );
theClassThatUsesCallback->Run();
}
};
I get this error
error C3374: can't take address of 'ClassThatProvidesCallback::MemberFunction'
unless creating delegate instance
When I research this, I find numerous explanations of how to call un-managed code from managed code ( and vice-versa ) I do not need to do this - all the code involved is managed. So I am hoping that someone can point me to a simple way to this.
This is full solution:
ref class ClassThatUsesCallback
{
public:
void setCallback( Action<String^>^ callback )
{
myCallback = callback;
}
void Run()
{
if( myCallback != nullptr ) {
myCallback("This is a test");
}
}
private:
Action<String^>^ myCallback;
};
ref class ClassThatProvidesCallback
{
public:
void MemberFunction( String^ s )
{
Console::WriteLine( "Member Function Callback " + s );
}
void Run()
{
ClassThatUsesCallback^ theClassThatUsesCallback
= gcnew ClassThatUsesCallback();
theClassThatUsesCallback->setCallback(gcnew Action<String^>(this,
&ClassThatProvidesCallback::MemberFunction));
theClassThatUsesCallback->Run();
}
};
int main(array<System::String ^> ^args)
{
ClassThatProvidesCallback^ c = gcnew ClassThatProvidesCallback();
c->Run();
return 0;
}
Native C++ style typedef is replaced with .NET Action delegate. Additional parameter this is added to setCallback call, it is required to define the class instance which contains the callback function.
I'm working on a couple of C++11 work queue classes. The first class, command_queue is a multi producer single consumer work queue. Multiple threads can post commands, and a single thread calls "wait()" and "pop_back()" in a loop to process those commands.
The second class, Actor uses command_queue and actually provides a consumer thread... besides that, the idea is that post() will return a future so that clients can either block until the command is processed, or continue running (actor also adds the idea of a result type). To implement this, I'm attempting to store std::promise's in a std::pair in the work queue. I believe I am fairly close, but i'm having a problem in the _entry_point function below... specifically, when I'm trying to get the std::pair out of the command queue I'm getting a "use of deleted function" compiler error... I'll put the actual error i'm getting from the compiler below the code (you should be able to save this to a text file and compile it yourself, it's stand alone c++11 code).
#include <mutex>
#include <condition_variable>
#include <future>
#include <list>
#include <stdio.h>
template<class T>
class command_queue
{
public:
command_queue() = default;
command_queue( const command_queue& ) = delete;
virtual ~command_queue() noexcept = default;
command_queue& operator = ( const command_queue& ) = delete;
void start()
{
std::unique_lock<std::recursive_mutex> g( _queueLock );
_started = true;
}
bool started()
{
return _started;
}
void stop()
{
std::unique_lock<std::recursive_mutex> g( _queueLock );
_started = false;
_queueCond.notify_one();
}
void post_front( const T& cmd )
{
std::unique_lock<std::recursive_mutex> g( _queueLock );
_queue.push_front( cmd );
_queueCond.notify_one();
}
void post_front( T&& cmd )
{
std::unique_lock<std::recursive_mutex> g( _queueLock );
_queue.push_front( cmd );
_queueCond.notify_one();
}
void wait()
{
std::unique_lock<std::recursive_mutex> g( _queueLock );
_queueCond.wait( g, [this](){return !this->_queue.empty() ? true : !this->_started;});
}
T pop_back()
{
std::unique_lock<std::recursive_mutex> g( _queueLock );
auto val = _queue.back();
_queue.pop_back();
return val;
}
private:
std::recursive_mutex _queueLock;
std::condition_variable_any _queueCond;
std::list<T> _queue;
bool _started = false;
};
template<class T, class U>
class actor
{
public:
actor() :
_started( false ),
_thread(),
_queue()
{
}
actor( const actor& ) = delete;
virtual ~actor() noexcept
{
if( _started )
stop();
}
actor& operator = ( const actor& ) = delete;
void start()
{
_started = true;
_queue.start();
_thread = std::thread( &actor<T,U>::_entry_point, this );
}
void stop()
{
_started = false;
_queue.stop();
_thread.join();
}
std::future<U> post( const T& cmd )
{
std::promise<U> p;
std::future<U> waiter = p.get_future();
_queue.post_front( std::pair<T,std::promise<U>>(cmd, std::move(p)) );
return waiter;
}
virtual U process( const T& cmd ) = 0;
protected:
void _entry_point()
{
while( _started )
{
_queue.wait();
if( !_started )
continue;
std::pair<T,std::promise<U>> item = _queue.pop_back();
item.second.set_value( process( item.first ) );
}
}
bool _started;
std::thread _thread;
command_queue<std::pair<T,std::promise<U>>> _queue;
};
class int_printer : public actor<int,bool>
{
public:
virtual bool process( const int& cmd ) override
{
printf("%d",cmd);
return true;
}
};
using namespace std;
int main( int argc, char* argv[] )
{
// std::promise<bool> p;
// list<std::pair<int,std::promise<bool>>> promises;
// promises.push_back( make_pair<int,std::promise<bool>>(10,std::move(p)) );
int_printer a;
a.start();
future<bool> result = a.post( 10 );
a.stop();
}
[developer#0800275b874e projects]$ g++ -std=c++11 pf.cpp -opf -lpthread
pf.cpp: In instantiation of ‘T command_queue<T>::pop_back() [with T = std::pair<int, std::promise<bool> >]’:
pf.cpp:133:65: required from ‘void actor<T, U>::_entry_point() [with T = int; U = bool]’
pf.cpp:99:9: required from ‘void actor<T, U>::start() [with T = int; U = bool]’
pf.cpp:163:13: required from here
pf.cpp:60:32: error: use of deleted function ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = int; _T2 = std::promise<bool>]’
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/utility:72:0,
from /usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/tuple:38,
from /usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/mutex:39,
from pf.cpp:2:
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/stl_pair.h:119:17: note: ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = int; _T2 = std::promise<bool>]’ is implicitly deleted because the default definition would be ill-formed:
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/stl_pair.h:119:17: error: use of deleted function ‘std::promise<_Res>::promise(const std::promise<_Res>&) [with _Res = bool]’
In file included from pf.cpp:4:0:
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/future:963:7: error: declared here
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/list:64:0,
from pf.cpp:5:
Promises aren't copyable (which makes sense - they represent a unique state). You need to use std::move in several places to transfer the unique ownership of the promise along.
Specifically, your home-brew queue class needs to permit moving, e.g.
auto val = std::move(_queue.back());
_queue.pop_back();
return val;
You protect writes to command_queue::_started with _queueLock, but not the read in command_queue::started(); this is a data race if some thread can call started while another thread is performing a modification (e.g., stop()).
Several small observations:
It doesn't make your program incorrect, but it's better to notify a condition variable outside the mutex. If you notify with the mutex held, another core may waste a microsecond or two scheduling a waiting thread to run only to immediately block on the mutex.
Your post_front(T&&) is copying the passed item into the queue due to missing a std::move:
_queue.push_front( cmd );
must be
_queue.push_front( std::move( cmd ) );
if you want it to actually be moved into the queue.
The predicate for the condition variable wait could be simplified from
[this](){return !this->_queue.empty() ? true : !this->_started;}
to
[this]{return !_queue.empty() || !_started;}
None of the command_queue member functions call other command_queue functions, so you could use a plain std::mutex instead of std::recursive_mutex and std::condition_variable instead of std::condition_variable_any.
You could use std::lock_guard<std::mutex> instead of std::unique_lock<std::mutex> to lock the mutex in every member function except wait. It's ever-so-slightly lighter weight.
You have the traditional pop exception-safety issue: If the selected move/copy constructor for T fails with an exception when returning from pop_back after modifying the queue, that element is lost. The way you've written the function makes this occurrence extremely unlikely, since
auto val = _queue.back();
_queue.pop_back();
return val;
(or after Kerrek's fix)
auto val = std::move(_queue.back());
_queue.pop_back();
return val;
should qualify for copy elision with a decent compiler, constructing the returned object in-place before the pop_back happens. Just be aware that if future changes impede copy elision you'll introduce the exception safety problem. You can avoid the issue altogether by passing a T& or optional<T>& as a parameter and move assigning the result to that parameter.
actor::_started is unnecessary since it's effectively a proxy for actor::_queue::_started.
I am writing an application using the OpenCV libraries, the Boost libraries and a pieve of code that I have downloaded from this LINK. I have created a project under the same solution with Thunk32 and I have the following files:
MainProject.cpp
#include "stdafx.h"
int main( int argc, char** argv )
{
IplImage *img = cvLoadImage( "C:/Users/Nicolas/Documents/Visual Studio 2010/Projects/OpenCV_HelloWorld/Debug/gorilla.jpg" );
Window::WindowType1 *win = new Window::WindowType1("Something");
cvNamedWindow( "window", CV_WINDOW_AUTOSIZE );
cvShowImage( "window", img );
cvSetMouseCallback( "oonga", (CvMouseCallback)win->simpleCallbackThunk.getCallback(), NULL );
while( true )
{
int c = waitKey( 10 );
if( ( char )c == 27 )
{ break; }
}
return 0;
}
Window.h
class Window {
public:
Window();
virtual ~Window();
//virtual void mouseHandler( int event, int x, int y, int flags, void *param );
private:
void assignMouseHandler( CvMouseCallback mouseHandler );
class WindowWithCropMaxSquare;
class WindowWithCropSelection;
class WindowWithoutCrop;
public:
typedef WindowWithCropMaxSquare WindowType1;
typedef WindowWithCropSelection WindowType2;
typedef WindowWithoutCrop WindowType3;
protected:
};
class Window::WindowWithCropMaxSquare : public Window {
public:
indev::Thunk32<WindowType1, void _cdecl ( int, int, int, int, void* )> simpleCallbackThunk;
WindowWithCropMaxSquare( char* name );
~WindowWithCropMaxSquare();
void _cdecl mouseHandler( int event, int x, int y, int flags, void *param );
private:
protected:
};
and Window.cpp
#include "stdafx.h"
Window::Window()
{
}
Window::~Window()
{
}
void Window::assignMouseHandler( CvMouseCallback mouseHandler )
{
}
Window::WindowWithCropMaxSquare::WindowWithCropMaxSquare( char* name )
{
simpleCallbackThunk.initializeThunk(this, &Window::WindowWithCropMaxSquare::mouseHandler); // May throw std::exception
}
Window::WindowWithCropMaxSquare::~WindowWithCropMaxSquare()
{
}
void _cdecl Window::WindowWithCropMaxSquare::mouseHandler( int event, int x, int y, int flags, void *param )
{
printf("entered mousehandler");
}
Now, when I run this, If I don't move the mouse inside the window, it's ok and the callback has been successfully passed to the cvSetMouseCallback function. The cvSetMouseCallback function has three parameters 1. the name of the window, 2. the CvMouseCallback and the NULL character. The CvMouseCallback is defined as
typedef void (CV_CDECL *CvMouseCallback )(int event, int x, int y, int flags, void* param);
and the CV_CDECL is just a redefinition of the _cdecl calling convention.
#define CV_CDECL __cdecl
Now, my mouseHandler function is a class member function, which I assume conforms to the _thiscall calling convention.
My question is, why do I get the following error just when I put my mouse on the window, if it has managed to get into the method at least once? I guess there's a change the second moment my mouse moves within the windoow. Can anyone help me please?
Here's an image with what I am doing:
That thunk code uses the __stdcall convention, not __cdecl. In this case, since cvSetMouseCallback takes a void* which it passes through to the callback, I would recommend that you use a static callback function and use this data pointer to pass the this pointer. You may then put your logic in this static function or else just call an instance version of the callback using the pointer that was passed in.
class Window {
public:
void _cdecl staticMouseHandler( int event, int x, int y, int flags, void *param ) {
((MouseHandler*)param)->mouseHandler(event, x, y, flags, NULL);
}
// ...
}
// ...
cvSetMouseCallback( "oonga", &Window::staticMouseHandler, win );