using STL smart pointers with COM interfaces - c++

I am trying to using the standard C++ library smart pointers with a library which uses MS COM for most of its function (I must say I am not well-versed with COM). So, I have the following custom deleter for my unique_ptr
struct COMDeleter {
template<typename T> void operator()(T* ptr) {
if (ptr) ptr->Release();
}
};
In the sample code, we have something like:
class MyClass
{
public:
MyClass(IDeckLink * device)
: m_deckLink(device)
{
}
MyClass::~MyClass()
{
if (m_deckLink != NULL)
{
m_deckLink->Release();
m_deckLink = NULL;
}
}
IDeckLink * m_deckLink;
};
This could be replaced with:
class MyClass
{
public:
MyClass(IDeckLink * device)
{
m_deckLink.reset(device);
}
std::unique_ptr<IDeckLink, COMDeleter> m_deckLink;
};
Now, I have another interface called IDeckLinkInput which I would like to wrap in a similar way but the way this is initialized is different as follows:
IDeckLinkInput* m_deckLinkInput = NULL;
if (m_deckLink->QueryInterface(IID_IDeckLinkInput, (void**) &m_deckLinkInput) != S_OK)
return false;
So, if I have a smart-pointer like:
std::unique_ptr<IDeckLinkInput, COMDeleter> m_deckLinkInput(nullptr);
I am not sure how I can use it with initialisation function like the above? Can it even be done or should i just stick to old style C++?

Something like this:
template<class U, class T>
std::unique_ptr<U, COMDeleter>
upComInterface( GUID guid, T const& src ) {
if (!src) return {};
T* r = nullptr;
if (src->QueryInterface( guid, (void**)&r) != S_OK)
return {};
return {r, {}};
}
then we:
auto deckLink = upComInterface<IDeckLinkInput>( IID_IDeckLinkInput, deckLink );
There is a minor DRY violation here -- the link between IDeckLinkInput and IID_IDeckLinkInput has to be repeated each time you do this, and getting it wrong leads to undefined behavior.
We can fix this via a number of mechanisms. Personally, I'd go with a tag dispatch type:
namespace MyComHelpers {
template<class T> struct com_tag_t {using type=T; constexpr com_tag_t(){};};
template<class T> constexpr com_tag_t<T> com_tag{};
template<class T>
constexpr void get_com_guid( com_tag_t<T> ) = delete; // overload this for your particular types
template<class T>
constexpr GUID interface_guid = get_com_guid( com_tag<T> );
}
Now we can associate the type with a guid. In the namespace of IDeckLinkInput do this:
constexpr GUID get_com_guid( MyComHelpers::com_tag_t<IDeckLinkInput> ) {
// constexpr code that returns the GUID
}
we then rewrite the get interface function:
std::unique_ptr<U, COMDeleter>
com_cast( T const& src ) {
if (!src) return {};
T* r = nullptr;
if (src->QueryInterface( MyComHelpers::interface_guid<T>, (void**)&r) != S_OK)
return {};
return {r, {}};
}
and use becomes:
auto declLink = com_cast<IDeckLinkInput>(m_deckLinkInput);
There are many ways to associate the type with the guid, including traits classes. The constexpr ADL-based lookup function and variable template is just one way.
Code not tested.

Related

tag dispatching for inherited classes

I have some code where I have a base class (lets call it foo) that has a variable number of derived classes (between 10-500) created by a generation script. Currently we have a function that will create a new base class by passing in its name as a string and then using a giant if/else statement to find the right one.
for example
if (name == "P2_26") {add_module(new P2_26());}
else if (name == "P4_30") {add_module(new P4_30());}
...
This leads to a giant if else block. This seems to me like code that could be simplified by using tag dispatching, but every example I find online uses built-ins like iterators that already have tags defined and I could not interpolate to my use case. Is there anyway to streamline this code?
Tag dispatched is based on type information as an input. Judging from your code you have a string as an input which which can not be used in run time.
Your case looks more like an abstract factory:
// Factory.h
class Base;
struct Factory {
using spawn_t = std::function<Base*()>;
using container_t = std::unordered_map<std::string, spawn_t>;
static container_t& producers() {
// This way it will be initialized before first use
static container_t producers;
return producers;
}
static Base* spawn(const std::string& name) {
auto it = producers().find(name);
if (it == producers().end()) return nullptr;
return it->second();
}
};
// Base.h
#define STR(x) #x
#define DEFINE_REGISTRATOR(_class_) \
DerivedRegistrator<_class_> _class_::_sRegistrator_(STR(_class_))
#define DECLARE_REGISTRATOR(_class_) \
static DerivedRegistrator<_class_> _sRegistrator_
template<typename T>
struct DerivedRegistrator{
DerivedRegistrator(const std::string& name) {
Factory::producers()[name] = [](){ return new T(); };
}
};
class Base {
// ...
};
And then generated files should include:
// Derived1.h
class Derived1 : public Base {
DECLARE_REGISTRATOR(Derived1);
// ...
};
// Derived1.cpp
DEFINE_REGISTRATOR(Derived1); // Will register automatically
This solution will register all classes automatically on program start which is more like what you had before.
UPD.
To use it you can simply replace all your if-else code with this line:
add_module(Factory::spawn(name));
Or if you can't handle nullptr in add_module:
Base* ptr = Factory::spawn(name);
if (ptr) {
add_module(ptr);
}
Thanks to D Drmmr for making this code better.
template<class T>
struct named_factory {
const char* name;
std::function<std::unique_ptr<T>()> factory;
};
struct find_factory {
using is_transparent=std::true_type;
struct named {
const char* str;
template<class T>
named(named_factory<T> const& f):str(f.name) {}
named(const char* name):str(name) {}
};
bool operator()(named lhs, named rhs) {
return strcmp(lhs.str, rhs.str)<0;
}
};
#define MAKE_STR2(X) #X
#define MAKE_STR(X) MAKE_STR2(X)
#define FACTORY(X,...) \
named_factory<__VA_ARGS__>{\
MAKE_STR(X),\
[]{\
return std::make_unique<X>()\
}\
}
Now we can:
std::set<named_factory<foo>, find_factory> factories = {
FACTORY(P2_26, foo),
FACTORY(P4_30, foo),
// ...
};
and in code you do:
bool add_module_by_name( const char* name ) {
auto it = factories.find(name);
if (it == factories.end()) return false;
auto module = it->factory();
if (!module) return false;
add_module( module.release() );
return true;
}
This is a data-driven design. The search for the right type is done in logarithmic time, not linear like your code. You could probably replace it with an unordered_map instead of a set.
However, if your type names are determined at compile time, you can do better. (Ie, if you have a hard coded "P2_26" at the call site).
template<class T>
struct tag_t { using type=T; constexpr tag_t(){} };
template<class T>
constexpr tag_t<T> tag{};
template<class T>
void add_module( tag_t<T> ) {
// ...
add_module( new T() );
}
Now you can add_module(tag<P2_26>) and skip the long if/else statement.
We can even hide the implementation of the outer add_module via this:
// in cpp file:
void add_module_impl( std::function< std::unique_ptr<foo>() > maker ) {
// ...
add_module( maker().release() );
}
// in h file:
void add_module_impl( std::function< std::unique_ptr<foo>() > maker );
template<class T>
void add_module( tag_t<T> t ) {
add_module_impl([]{ return std::make_unique<T>(); });
}
and again, we can add_module(tag<P4_30>) and it just works.

Non-copying std::shared_ptr<boost::any>?

I store "instances of different types" with "shared ownership". That's what I currently do:
class Destructible {
public:
virtual ~Destructible() = default;
};
// UGLY
class MyType1 : public Destructible { ... };
class MyTypeN : public Destructible { ... };
class Storage {
std::vector<std::shared_ptr<Destructible>> objects_;
...
}
I'd love to switch to boost::any, removing all these conformances and gaining the ability to store instances of truly any type. Also I like boost::any interface and boost::any_cast.
But my types don't satisfy ValueType requirements, they are not copyable. What is the best (preferably existing) solution for this problem? Something like shared_any_ptr, which captures destructor at creation, has type erasure, reference counter and can do any_cast.
Edit: boost::any allows creation with move, but I'd prefer not to even move and use pointers.
Edit2: I also use make_shared extensively, so something make_shared_any_ptr would come in handy.
This isn't tricky with shared pointers. We can even avoid multiple allocations.
struct any_block {
any_block(any_block const&)=delete;
template<class T>
T* try_get() {
if (!info || !ptr) return nullptr;
if (std::type_index(typeid(T)) != std::type_index(*info)) return nullptr;
return static_cast<T*>(ptr);
}
template<class T>
T const* try_get() const {
if (!info || !ptr) return nullptr;
if (std::type_index(typeid(T)) != std::type_index(*info)) return nullptr;
return static_cast<T const*>(ptr);
}
~any_block() {
cleanup();
}
protected:
void cleanup(){
if (dtor) dtor(this);
dtor=0;
}
any_block() {}
std::type_info const* info = nullptr;
void* ptr = nullptr;
void(*dtor)(any_block*) = nullptr;
};
template<class T>
struct any_block_made:any_block {
std::aligned_storage_t<sizeof(T), alignof(T)> data;
any_block_made() {}
~any_block_made() {}
T* get_unsafe() {
return static_cast<T*>((void*)&data);
}
template<class...Args>
void emplace(Args&&...args) {
ptr = ::new((void*)get_unsafe()) T(std::forward<Args>(args)...);
info = &typeid(T);
dtor = [](any_block* self){
static_cast<any_block_made<T>*>(self)->get_unsafe()->~T();
};
}
};
template<class D>
struct any_block_dtor:any_block {
std::aligned_storage_t<sizeof(D), alignof(D)> dtor_data;
any_block_dtor() {}
~any_block_dtor() {
cleanup();
if (info) dtor_unsafe()->~D();
}
D* dtor_unsafe() {
return static_cast<D*>((void*)&dtor_data);
}
template<class T, class D0>
void init(T* t, D0&& d) {
::new( (void*)dtor_unsafe() ) D(std::forward<D0>(d));
info = &typeid(T);
ptr = t;
dtor = [](any_block* s) {
auto* self = static_cast<any_block_dtor<D>*>(s);
(*self->dtor_unsafe())( static_cast<T*>(self->ptr) );
};
}
};
using any_ptr = std::shared_ptr<any_block>;
template<class T, class...Args>
any_ptr
make_any_ptr(Args&&...args) {
auto r = std::make_shared<any_block_made<T>>();
if (!r) return nullptr;
r->emplace(std::forward<Args>(args)...);
return r;
}
template<class T, class D=std::default_delete<T>>
any_ptr wrap_any_ptr( T* t, D&& d = {} ) {
auto r = std::make_shared<any_block_dtor<std::decay_t<D>>>();
if (!r) return nullptr;
r->init( t, std::forward<D>(d) );
return r;
}
you'd have to implement any_cast, but with try_get<T> it should be easy.
There may be some corner cases like const T that the above doesn't handle.
template<class T>
std::shared_ptr<T>
crystalize_any_ptr( any_ptr ptr ) {
if (!ptr) return nullptr;
T* pt = ptr->try_get<T>();
if (!pt) return nullptr;
return {pt, ptr}; // aliasing constructor
}
This lets you take a any_ptr and turn it into a shared_ptr<T> if the types match without copying anything.
live example.
You'll notice how similar any_block_made and any_block_dtor is. I believe that this is why at least one major shared_ptr in a std library reuses the spot the deleter lives in for make_shared itself.
I could probably do similar, and reduce binary size here. In addition, the T/D parameter of any_block_made and any_block_dtor is really just about how big and aligned the block of memory we play with is, and what exactly type erasued helper I store in the dtor pointer in the parent. A compiler/linker with COMDAT folding (MSVC or GOLD) may eliminate the binary bloat here, but with a bit of care I could do it myself.

Bypass a template error with a private destructor

In compile time, I've got the following issue, how to make this compile, because conceptually for me it's correct, any suggestions of refactoring are welcome.
I got a compile error because "Search" destructor is private but I won't use delete on a Search pointer since I provided a custom Deleter in the initialization of the base class. I know that the compiler doesn't know that, how to bypass it.
error description :
error C2248: cannot access private member declared in class 'Search'
compiler has generated 'Search::~Search' here
class Search
{
public:
static Search* New(/* */); // using a pool of already allocated objects to avoid expensive allocations
static void Delete(Search*);
private:
Search(/* */) {/* */}
~Search() {/* */}
};
template<class T>
class MyList
{
public:
typedef (*CustomDeleter) (T* pElement);
MyList(CustomDeleter lpfnDeleter = NULL) {};
void Empty()
{
for (/**/)
{
if (m_pList[m_nListLastUsed])
{
if (m_lpfnCustomDeleter == NULL)
delete m_pList[m_nListLastUsed]; // COMPILE ERROR HERE BECAUSE Search destructor is private BUT I won't use that instruction since
// I provided a custom Deletern I know that the compiler doesn't know that, how to bypass it
else
m_lpfnCustomDeleter(m_pList[m_nListLastUsed]);
}
}
}
private:
T** m_pList;
CustomDeleter m_lpfnCustomDeleter; // Pointer to a custom deleter
};
class Query : public MyList<Search>
{
public:
Query() : MyList<Search>(&Search::Delete) // I set a custom deleter since Search hides its destructor : is this the right way ?
{}
~Query()
{
/****/
Empty(); // PROBLEM HERE
/***/
}
};
Make sure that 'm_lpfnCustomDeleter' is never NULL or better nullptr. You can make sure of this by falling back to a default 'deleter' if the user does not provide with any custom deleter.
I would prefer something like below.
#include <iostream>
template <typename PointerType>
struct DefaultDeleter {
void operator()(PointerType* ptr) {
std::cout << "Delete\n";
}
};
struct CustomDeleter {
void operator()(int* ptr) {
std::cout << "Custom int deleter" << std::endl;
}
};
template <typename T, typename Deleter = DefaultDeleter<T>>
class Whatever
{
public:
Whatever() {
std::cout << "Cons\n";
}
void deinit() {
Deleter d;
auto v = new T;
d(v); // Just for the sake of example
}
};
int main() {
Whatever<char> w;
w.deinit();
Whatever<int, CustomDeleter> w2;
w2.deinit();
return 0;
}
Updated :: W/o code refactoring
Assuming w/o c++11
Have this small metaprogram added to your code base.
namespace my {
template <typename T, typename U> struct is_same {
static const bool value = false;
};
template <typename T>
struct is_same<T, T> {
static const bool value = true;
};
template <bool v, typename T = void> struct enable_if;
template <typename T = void> struct<true, T> {
typedef T type;
};
}
Change your Empty function to:
void Empty() {
for (/****/) {
do_delete();
}
}
template <typename =
typename my::enable_if<my::is_same<T, Search>::value>::type>
void do_delete() {
assert (m_lpfnCustomDeleter != NULL);
m_lpfnCustomDeleter(m_pList[m_nListLastUsed]);
}
void do_delete() {
delete m_pList[m_nListLastUsed];
}
If you are using c++11, the you dont have to write the metaprogram under namespace 'my'. Just replace 'my::is_same' and 'my::enable_if' with 'std::is_same' and 'std::enable_if'.
Note:, Have not compiled and tested the above code.
Separate the code doing the deleting from the rest:
if (m_pList[m_nListLastUsed])
{
if (m_lpfnCustomDeleter == NULL)
delete m_pList[m_nListLastUsed]; // COMPILE ERROR HERE BECAUSE Search destructor is private BUT I won't use that instruction since
// I provided a custom Deletern I know that the compiler doesn't know that, how to bypass it
else
m_lpfnCustomDeleter(m_pList[m_nListLastUsed]);
}
Replace the code above by a call to:
custom_delete(m_pList[m_nListLastUsed]);
Then add it as a method of your list class, don't forget to include <type_traits> as well:
std::enabled_if<std::is_destructible<T>::value, void>::type custom_delete(T* ptr) {
/* Note: this isn't pre-2000 anymore, 'lpfn' as a prefix is horrible,
don't use prefixes! */
if (m_lpfnCustomDeleter) {
m_lpfnCustomDeleter(ptr);
} else {
delete ptr;
}
}
std::enabled_if<!std::is_destructible<T>::value, void>::type custom_delete(T* ptr) {
if (!m_lpfnCustomDeleter) {
throw "No custom deleter for a non destructible type!";
}
m_lpfnCustomDeleter(ptr);
}
enabled_if will make it so that the function where it can delete the object directly doesn't exist in your list if the object has a private destructor.
Alternatively, you could pass a structure (or function) acting as a custom deleter as the second template argument of your list with a default value as one that calls the delete operator, then directly call this structure on your pointer, as in Arunmu's anser.

Design Pattern, adding data to a class (3rd party) without modifying it

When I have to extend the behaviour of a class without modifying it, I often use the design pattern visitor. It adds member-like functions without modifying the core of the class it works with.
More or less in the same way, I need to extend a third party class, but mostly with data, not behaviour.
In such cases, I often use a std::map matching the a key MyClass* with a value MyClassExtender. MyClassExtender contains all the additionnal information.
While doing that, I happened to wonder if there are other ways of doing that, maybe more common or more 'best-practice". Should I call this additive class an Extender ?
Is there a name for such a pattern...
Nota Bene: I could have simply aggregated the MyClass* and MyClassExtender in a new class, but I need to access MyClassExtender given a MyClass* really often, so the st::map is really convinient.
Why don't you just subclass the class? Inheritance is the way to extend classes, whether with behavior or state. Unless you just want to associate instances of the class with other data, in which case it's not extending at all, and a std::map is the right answer.
So - create your MyClass object with in the struct with your extension objects:
struct MyClassEx {
MyClassExtension extension;
MyClass object;
};
To make it more robustness for different types - use templates from the example: http://ideone.com/mmfK83
The solution below is inspired by std::shared_ptr/std::make_shared:
template <typename Type>
struct LinkExtension;
template <typename Type>
struct TypeEx {
using Extension = typename LinkExtension<Type>::Type;
alignas(Type) uint8_t objectData[sizeof(Type)];
alignas(Extension) uint8_t extensionData[sizeof(Extension)];
Type* getObject() { return reinterpret_cast<Type*>(objectData); }
const Type* getObject() const { return reinterpret_cast<const Type*>(objectData); }
Extension* getExtension() { return reinterpret_cast<Extension*>(extensionData); }
const Extension* getExtension() const { return reinterpret_cast<const Extension*>(extensionData); }
template <class... Args>
TypeEx(Args&&... args)
{
new (objectData) Type(std::forward<Args>(args)...);
new (extensionData) Extension();
}
~TypeEx()
{
getObject()->~Type();
getExtension()->~Extension();
}
TypeEx(const TypeEx&) = delete;
TypeEx& operator = (const TypeEx&) = delete;
};
And some helper functions:
template <typename Type, class... Args>
Type* createObjectEx(Args&&... args)
{
TypeEx<Type>* retVal = new TypeEx<Type>(std::forward<Args>(args)...);
return retVal->getObject();
}
template <typename Type>
typename LinkExtension<Type>::Type& getObjectEx(Type* obj)
{
static_assert(std::is_standard_layout<TypeEx<Type>>::value, "Oops");
static_assert(offsetof(TypeEx<Type>, objectData) == 0, "Oops");
TypeEx<Type>* retVal = static_cast<TypeEx<Type>*>((void*)obj);
return *(retVal->getExtension());
}
template <typename Type>
const typename LinkExtension<Type>::Type& getObjectEx(const Type* obj)
{
static_assert(std::is_standard_layout<TypeEx<Type>>::value, "Oops");
static_assert(offsetof(TypeEx<Type>, objectData) == 0, "Oops");
const TypeEx<Type>* retVal = static_cast<const TypeEx<Type>*>((const void*)obj);
return *(retVal->getExtension());
}
template <typename Type>
void deleteObjectEx(const Type* obj)
{
const TypeEx<Type>* objectEx = static_cast<const TypeEx<Type>*>((const void*)obj);
delete objectEx;
}
And how to link extension to class:
class MyClass {
public:
virtual ~MyClass() = default;
};
struct MyClassExtension {
int a;
int b;
};
template <>
struct LinkExtension<MyClass> {
using Type = MyClassExtension;
};
And proof it works:
void printExtension(MyClass* object);
int main() {
MyClass* object = createObjectEx<MyClass>();
MyClassExtension& extension = getObjectEx(object);
extension.a = 1;
extension.b = 2;
printExtension(object);
deleteObjectEx(object);
TypeEx<MyClass> objectEx;
objectEx.getExtension()->a = 3;
objectEx.getExtension()->b = 4;
printExtension(objectEx.getObject());
}
void printExtension(MyClass* object)
{
MyClassExtension& extension = getObjectEx(object);
std::cout << extension.a << ' ' << extension.b << std::endl;
}
If your compiler does not support variadic templates, the solution is still possible, but requires more hand work to be complete.

Is it possible to determinate at run time is pointer points to C++ class or at Objective-C class?

Question is in subject.
I want to write some universal template function for safe deleting objects and wondering is it possible to use something like this:
template< class T > void SafeDelete( T*& pVal )
{
if(objc_is_cpp_object(pVal)){
delete pVal;
pVal = NULL;
}
else
[pVal release]
}
As mentioned in comments, I would suggest not to mix the C++ delete and Objective-C release.
Just for technical point of view, you can use the following SFINAE trick runtime:
template<typename T> struct void_ { typedef void type; };
template<typename, typename = void>
struct CppType { static const bool value = false; };
template<typename T>
struct CppType<T, typename void_<int (T::*)>::type> { static const bool value = true; };
template< class T >
void SafeDelete( T*& pVal )
{
if(CppType<T>::value || std::is_pod<T>::value) { // <-----
delete pVal;
pVal = 0;
}
else {
// [pVal release];
}
}
Possibly, is_pod is available in C++11, boost etc. But it's easy to implement.
Objective-C pointers are the same as C++ pointers: 4-to-8 word integer values that point to various objects in memory. The Objective-C compiler supports outputting values in with multiple formats, such as C, C++, and Objective-C object layouts.
That's it. There really isn't much beyond that.
You can try to do something hacky like create a class where a field always contains a magic value:
template <class T>
class Magic {
private:
const char magic[] = 1234567;
public:
bool is_object() const {
return magic == 1234567;
}
}
then you could test it like so:
bool is_cpp(void *ptr) {
return ((Magic*) ptr)->is_object();
}
But be forewarned that this is extremely hacky.