What is call "Transparent Class Wrapper" in C++
Why it is call "Transparent..."
What is the use of it (What cannot do without 'Transparent Class Wrapper').
Appreciate some conceptual explanation.
A transparent class wrapper is a wrapper around a type, where the wrapper behaves the same as the underlying type - hence "transparent".
To explain it as well as its use, here's an example where we wrap an int but overload operator++() to output a message whenever it is used (inspired by this thread):
class IntWrapper {
int data;
public:
IntWrapper& operator++() {
std::cout << "++IntWrapper\n";
data++;
return *this;
}
IntWrapper(int i) : data(i) {}
IntWrapper& operator=(const IntWrapper& other)
{
data = other.data;
return *this;
}
bool operator<(const IntWrapper& rhs) const { return data < rhs.data; }
// ... other overloads ...
};
We can then replace usages of int with IntWrapper if we choose to:
for (int i = 0; i < 100; ++i) { /* ... */ }
// becomes
for (IntWrapper i = 0; i < 100; ++i) { /* ... */ }
Except the latter will print a message whenever preincrement is called.
Note that I supplied a non-explicit constructor IntWrapper(int i). This ensures that whenever I use an int where an IntWrapper is expected (such as IntWrapper i = 0), the compiler can silently use the constructor to create an IntWrapper out of the int. The Google C++ style Guide discourages single-argument non-explicit constructors for precisely this reason, as there may be conversions where you didn't expect, which hurts type safety. On the other hand, this is exactly what you want for transparent class wrappers, because you do want the two types to be readily convertible.
That is:
// ...
explicit IntWrapper(int i) ...
// ...
IntWrapper i = 0; // this will now cause a compile error
Most likely, you're referring to a lightweight inline (header file) wrapper class, though I'm not familiar with the term. Adding a level of abstraction like this is useful in permitting generic client code.
Related
I would like to have an int wrapper class that behaves like int without the need to overload all of the operators. The same question was asked but not really answered here. I know I can write a template wrapper and overload dozens of operators to achieve that (in fact, I have it like that now - basically it looks like this mess). However it would be nice if it would be possible to somehow expose the internal primitive type without the need to overload the operators that just forward the call to it.
Is that possible? Perhaps by overloading dereferencing operators or somesuch?
EDIT: Example code:
template<typename T>
class IDWrapper
{
public:
inline IDWrapper() { }
inline IDWrapper(T id) : m_Value(id) { }
constexpr static int size() { return sizeof(T); }
constexpr static T min() { return std::numeric_limits<T>::min(); }
constexpr static T max() { return std::numeric_limits<T>::max(); }
inline bool isValid() const { return m_Value != 0; }
inline operator T() const { return m_Value; }
inline operator T&() { return m_Value; } //this line was the attempt to make it transparent... unsuccessfully
inline IDWrapper &operator=(T v) { m_Value = v; return *this; }
inline void invalidate() { m_Value = 0; }
private:
T m_Value = 0;
};
Basically it wraps an ID of type T in a "special" way so that it gives convenient options for validating and invalidating it. Plus it gives convenient access the the size and min/max. The reason for the templated wrapper is that I will need to replace it later with base64 number or some other non-standard number type and I need the interface that relies on the IDWrapper to stay consistent. The numerical operators will still be provided by T so when I spell them out here I am just forwarding the call hence the question.
So I have fiddled with it inspired by the comments to the OP and it seems that having these two (and only these two) overloaded operators can do the trick:
operator T&() { /*...*/ }
operator const T&() const { /*...*/ }
Naturally it is not without the cost. For example if T is an int (or any type for which sizeof(T) < sizeof(void*)) then returning const reference to it is more expensive than doing a copy (but having a copy operator breaks the transparency). Not to mention memory address lookup. I am not sure about potential other problems with this so feel free to comment/answer. But this works.
How do I make a class in C++, when initialized, return a Boolean value when its name is invoked, but no explicit function call make, like ifstream. I want to be able to do this:
objdef anobj();
if(anobj){
//initialize check is true
}else{
//cannot use object right now
}
not just for initialization, but a check for its ability to be used.
The way istream does it is by providing an implicit conversion to void*
http://www.cplusplus.com/reference/iostream/ios/operator_voidpt/
stream output and implicit void* cast operator function invocation
Update In reaction to the comments, the Safe Bool Idiom would be a far better solution to this: (code directly taken from that page)
class Testable {
bool ok_;
typedef void (Testable::*bool_type)() const;
void this_type_does_not_support_comparisons() const {}
public:
explicit Testable(bool b=true):ok_(b) {}
operator bool_type() const {
return ok_==true ?
&Testable::this_type_does_not_support_comparisons : 0;
}
};
template <typename T>
bool operator!=(const Testable& lhs,const T& rhs) {
lhs.this_type_does_not_support_comparisons();
return false;
}
template <typename T>
bool operator==(const Testable& lhs,const T& rhs) {
lhs.this_type_does_not_support_comparisons();
return false;
}
The article by Bjorn Karlsson contains a reusable implementation for the Safe Bool Idiom
Old sample:
For enjoyment, I still show the straight forward implementation with operator void* overloading, for clarity and also to show the problem with that:
#include <iostream>
struct myclass
{
bool m_isOk;
myclass() : m_isOk(true) { }
operator void* () const { return (void*) (m_isOk? 0x1 : 0x0); }
};
myclass instance;
int main()
{
if (instance)
std::cout << "Ok" << std::endl;
// the trouble with this:
delete instance; // no compile error !
return 0;
}
This is best accomplished using the safe bool idiom.
You provide an implicit conversion to a member-function-pointer, which allows instances of the type to be used in conditions but not implicitly convertyed to bool.
You need a (default) constructor and an operator bool()().
class X {
public:
operator bool ()const{
//... return a boolean expression
}
};
usage:
X x; // note: no brackets!
if( x ) {
....
}
You'll want to create an operator bool function (or as boost does, an unspecified_bool_type that has certain improved properties I can't recall offhand). You may also want to create operator! (For some reason I seem to recall iostreams do this too).
I'm trying to wrap a C library which uses patterns like this:
Thing* x= new_thing_("blah");
Thing* tmp= thing_copy(x);
free_thing(tmp);
Other* y=get_other(x,7);
char* message=get_message(x,y);
free_thing(x);
free_other(y);
In c++, I'd like to be able to do something like
auto_ptr<CXXThing> x=new CXXThing("blah");
auto_ptr<CXXThing> tmp=new CXXThing(*x);
auto_ptr<CXXOther> y=x->get_other(7);
char* message = y->get_message();
Obviously, CXXOther wraps a pointer to a CXXThing as well. So the problem I'm encountering is that essentially I'd like to just "insert" functions and members into existing structs (I think this is known as the "Mixin" idea).
The problem is that if I include a Thing as an element of the CXXThing, then I don't know how I'd declare the constructor, and if I include a pointer to the wrapped class, then I have an extra level of useless indirection.
How should I wrap it so that this is possible? (An answer of "What you want to do is not best/possible... here is the proper way" is also acceptable.)
Instead of using auto_ptrs, you can use the RAII idiom more directly. Here's one way you can do it:
A CXXThing class that wraps a Thing:
class CXXThing
{
public:
// Acquire a Thing
explicit CXXThing(const char* str) : x(::new_thing_(str)) {}
// Copy a Thing
CXXThing(const CXXThing& rhs) : x(::thing_copy(rhs.x)) {}
// Copy-and-swap idiom
CXXThing& operator=(CXXThing rhs)
{
swap(*this, rhs);
return *this;
}
// Release a Thing
~CXXThing() { ::free_thing(x); }
friend void swap(CXXThing& lhs, CXXThing& rhs)
{
Thing* tmp = lhs.x;
lhs.x = rhs.x;
rhs.x = tmp;
}
private:
Thing* x;
friend class CXXOther;
};
A CXXOther class that wraps an Other:
class CXXOther
{
public:
// Acquire an Other
explicit CXXOther(CXXThing& thing, int i) : y(::get_other(thing.x, i)) {}
// Release an Other
~CXXOther() { ::free_other(y); }
// Get a message
char* get_message(const CXXThing& x) { return ::get_message(x.x, y); }
private:
// Instaces of Other are not copyable.
CXXOther(const CXXOther& rhs);
CXXOther& operator=(const CXXOther& rhs);
Other* y;
};
Translating your C code into C++ code with the above classes:
int main()
{
CXXThing x("blah");
{
CXXThing tmp = x;
} // tmp will go away here.
CXXOther y(x, 7);
char* msg = y.get_message(x);
return 0;
}
I was implementing (for training purpose) a Bubble Sort template function:
template<typename iterInput,
typename predicate>
void BubbleSort(iterInput first1,iterInput last1,predicate func)
{
bool swapped(false);
do
{
swapped = false;
iterInput begin = first1;
iterInput beginMinus = first1;
++begin;
for (;begin != last1; begin++,beginMinus++)
{
if (func(*beginMinus,*begin) )
{
std::swap(*beginMinus,*begin);
swapped = true;
}
}
}
while(swapped);
}
When I have realized that this function will not work for class with no assignment operator, like this one (forgive me for the bad name):
class NoCopyable
{
public:
explicit NoCopyable(int value) : value_(value) {}
NoCopyable(const NoCopyable& other) : value_(other.value_) {}
~NoCopyable() {}
bool operator<(const NoCopyable& other) { return value_ < other.value_; }
void setValue(int value) { value_ = value; }
std::ostream& print(std::ostream& os) const { return os << value_; }
private:
NoCopyable& operator=(const NoCopyable& other);
int value_;
};
std::ostream& operator<<(std::ostream& os, const NoCopyable& obj)
{
return obj.print(os);
}
struct PrintNoCopyable
{
void operator()(const NoCopyable& noCopyable) { std::cout << noCopyable << '\n'; }
};
The compiler raises this error Error 1 error C2248: 'NoCopyable::operator =' : cannot access private member declared in class 'NoCopyable'
So, I have slightly modify the code using instead of the std::swap function my version of the swap function, here is the code:
template<typename T1,
typename T2>
void noAssignmentSwap(T1& t1,T2& t2)
{
T1 temp(t1);
t1.~T1();
new (&t1) T1(t2);
t2.~T2();
new (&t2) T2(temp);
}
The code compiles and gives the right result. However I am not completely sure, I remember a Sutter's article that suggest you to avoid playing with the objects life time. The article just warns you by playing with fire without actually giving you any real reason. I can see problem in exception safety if the copy constructor of T1 or T2 can throw. However there is the same problem in the standard version if the assignment operator is allowed to throw.
Here the question, can you see any possible drawbacks in this version of swap?
Cheers
Apart from anything else, if a class does not have an assignment operator, its designer probably did not intend it to be swapped. If they did that, they probably disabled copy construction too, so your new swap function still won't work.
As for your assertion that Standard Library containers do not need assignment - that is true so long as you don't want to actually do anything useful with them. Does this code compile for you?
#include <vector>
using namespace std;
struct A {
private:
void operator=( const A &);
};
int main() {
vector <A> v;
v.push_back( A() );
v[0] = A(); // assignment needed here
}
I think it won't.
The difference is that when the assignment operator fails, you still have the same number of objects.
If you destroy one object and fail to create a new one, one object is lost! If it was part of a container, the container's state is probably also invalid.
You need a copy ctor instead of an assignment operator, but the two are sufficiently similar that at least in a typical case, you'll have both or you'll have neither. IOW, I don't think this generally accomplishes much.
I'd class it right along side the xor-swap trick: interesting, but generally useless.
It might be confusing to a future maintainer of the code.
I'm trying to develop a pretty simple (for now) wrapper class around int, and was hoping to overload the = operator to achieve something like the following:
class IntWrapper
{
...
private:
int val;
}
int main ( )
{
IntWrapper a;
int b;
a = 5; // uses overloaded = to implement setter
b = a; // uses overloaded = to implement getter
}
I'm gathering however that this can't be done. Implementing the setter is pretty straightforward, something like:
class IntWrapper
{
...
IntWrapper& operator = (int rhs) { this.val = rhs; return *this; }
...
}
However, from a bit of Googling I'm gathering there's no way to do the getter in this way. My understanding is that this is because the = operator can only be overridden to assign to a variable, and since int is a primitive type we cannot override its default implementation of =. Is this correct? If not, how do I go about writing the getter?
If that is correct, does anyone have any elegant suggestions for something similar? About the nearest I can find is overloading a conversion operator:
class IntWrapper
{
...
operator int( ) { return this.val; }
...
}
int main ( )
{
...
b = (int) a;
...
}
To me though that seems pretty pointless, as its barely any better than a simple getVal() method.
Thanks for any suggestions!
You don't need a cast to invoke the conversion function. A plain
b = a;
will invoke it too. That way, i can see how that's more convenient to use than a getVal function. Although i generally don't use conversion functions. I would prefer an explicit getVal function. In particular consider this one
struct W {
W(int);
operator int();
};
int main() {
W w = 42;
int a = true ? 0 : w; // Ambiguity! What conversion direction?
}
It quickly gets out of hand...
What you suggest is the way to go, and I use it all the time. You shouldn't need to cast a to an int. The compiler is smart enough to see the b is an int and it will automatically call the operator int cast operator for you.