C++ Class Wrapper Around Fundamental Types

C++ Class wrapper around fundamental types

1) Is there any additional function calling overhead when using someClass.operator+()

No, if the function body is small and in the header, it will be inlined, and have no overhead

2) Is there a way to automatically make the compiler cast the floatWrapper to a float?

struct floatWrapper {
floatWrapper(float); //implicit conversion from float
operator float(); //implicit conversion to float.
};

Again, if the body of the function is small and in the header, it will be inlined, and have no overhead

3) Is there any additional memory overhead?

not if there's no virtual functions. A class is called polymorphic if it declares or inherits any virtual functions. If a class is not polymorphic, the objects do not need to include a pointer to a virtual function table. Moreover, performing dynamic_cast of a pointer/reference to a non-polymorphic class down the inheritance hierarchy to a pointer/reference to a derived class is not allowed, so there is no need for the objects to have some kind of type information.

4) Are there any other problems / performance impacts this could cause?

performance? No.

Also, be sure to implement binary operators that don't modify the lhs as free functions, and overload them to support all relevant permutations of floatWrapper and float.

struct floatWrapper {
explicit floatWrapper(float);
operator float(); //implicit conversion to float.
floatWrapper operator-=(float);
};
floatWrapper operator-(floatWrapper lhs, floatWrapper rhs)
{return lhs-=rhs;}
floatWrapper operator-(float lhs, floatWrapper rhs)
{return floatWrapper(lhs)-=rhs;}
floatWrapper operator-(floatWrapper lhs, float rhs)
{return lhs-=rhs;}

Here's my attempt at such a thing. Note you'll need a slightly different version for float/double/long double.

Wrapper Classes for Primitive Data Types

C++11 has explicit operator overloads.

struct silly_wrapper {
int foo;
explicit operator int&() { return foo; }
};

void primitive_increment(int& x) { ++x; }

int main()
{
silly_wrapper x;
primitive_increment(x); // works
x += 1; // doesn't work - can't implicitly cast
}

C++ wrapper around any collection type using templates

I started reading about template specialization to see if that'd be
any help, however I don't think this would provide a solution as the
type contained within the set would have to be known.

You can partially specialize MySack to work with std::set.

template <class T>
class MySack<std::set<T>> {
//...
};

However, this has the disadvantage that the partial specialization replaces the whole class definition, so you need to define all member variables and functions again.

A more flexible approach is to use policy-based design. Here, you add a template parameter that wraps the container-specific operations. You can provide a default for the most common cases, but users can provide their own policy for other cases.

template <class C, class V = typename C::value_type>
struct ContainerPolicy
{
static void push(C& container, const V& value) {
c.push_back(value);
}
static void pop(C& container) {
c.pop_back();
}
};

template <class C, class P = ContainerPolicy<C>>
class MySack
{
Collection c;

public:
typedef typename Collection::value_type value_type;

void add(const value_type& value) {
P::push(c, value);
}
};

In this case, it is easier to provide a partial template specialization for the default policy, because it contains only the functionality related to the specific container that is used. Other logic can still be captured in the MySack class template without the need for duplicating code.

Now, you can use MySack also with your own or third party containers that do not adhere to the STL style. You simply provide your own policy.

struct MyContainer {
void Add(int value);
//...
};

struct MyPolicy {
static void push(MyContainer& c, int value) {
c.Add(value);
}
};

MySack<MyContainer, MyPolicy> sack;

What is the meaning of a C++ Wrapper Class?

A "wrapper class" is a de facto term meaning a class that "wraps around" a resource; i.e, that manages the resource. When people write a wrapper, then, they are doing something like this:

class int_ptr_wrapper
{
public:
int_ptr_wrapper(int value = 0) :
mInt(new int(value))
{}

// note! needs copy-constructor and copy-assignment operator!

~int_ptr_wrapper()
{
delete mInt;
}

private:
int* mInt;
};

This class manages ("wraps") a pointer to an int. All resources should be wrapped in some fashion, for cleanliness (no explicit clean up code or noise) and correctness (destructor is guaranteed to run; cannot forget to clean up, and safe with exceptions).

This pattern is called Scoped-bound Resource Management (SBRM), though a far more common (but most esoteric) name is Resource-Acquisition is Initialization (RAII). The idea is to bind a resource's clean-up to a destructor, for the reasons given above: the scope handles the rest.

Note that I said it was missing a copy-constructor and copy-assignment operator. This is due to the Rule of Three. (See linked question for detailed explanation.) The simplest way to correctly implement this rule is with the copy-and-swap idiom, explained here.


Sometimes, it's not pragmatic to write wrapper class for resource clean-up, usually when the resource is unique or used once. (Or with transactional programming.) The solution to this is called scope guard, a way of writing clean-up code inside the function that needs it.

You may find more information by searching for it in your favorite search provider (that is, Google), or going to the "primary" document here. Note that Boost provides a utility for this, as it usually does for good idioms.

How to create a C++ wrapper class for the following kind of C program?

Just create a class and put the code inside, for example in your .h file:

class EventWrapper
{
public:
EventWrapper();
static int Event1Handler();
static void Event2Handler();
}

Then in your .cpp file:

#include "EventWrapper.h"
// Include relevant headers for your USB device

EventWrapper::EventWrapper()
{
// Code to setup calls to Event1handler() and Event2handler()
// using Open Sound Control methods.
}

int EventWrapper::Event1Handler()
{
// Code to process event 1
}

void EventWrapper::Event2Handler()
{
// Code to process event 2
}

Without knowing all of the details of your program you may have to play around with what is static and how you want to handle it.



Related Topics



Leave a reply



Submit