copying classes

Started by
24 comments, last by mfawcett 19 years ago
I would have to search for it :P So here's the code again:

// introspect.h header with a bunch of evil macros
#ifndef INTROSPECT_H#define INTROSPECT_Htypedef char (&n)[1];typedef char (&y)[2];template< bool condition, typename T> struct enable_if {};template< typename T > struct enable_if<true,T> { typedef T type; };#define INTROSPECT_IMPL(id, ret, func, cflag, ...) template< typename T, ret (T::*)(__VA_ARGS__) cflag> struct has_##id##_pfn {}; template< typename T > n has_##id##_x(...); template< typename T > y has_##id##_x(int, has_##id##_pfn<T, &T::func >* p = 0); template< typename T > struct has_##id {    enum { value = sizeof(has_##id##_x<T>(0)) == sizeof(y) }; }#define INTROSPECT(id, ret, func, ...) INTROSPECT_IMPL(id, ret, func,, __VA_ARGS__)#define INTROSPECT_CONST(id, ret, func, ...) INTROSPECT_IMPL(id, ret, func, const, __VA_ARGS__)#define WHEN_AVAILABLE(id, ret) template<typename T> typename enable_if<has_##id<T>::value,ret>::type#define WHEN_UNAVAILABLE(id, ret) template<typename T> typename enable_if<!has_##id<T>::value,ret>::type#define WHEN_AVAILABLE_INLINE(id, ret) template<typename T> inline typename enable_if<has_##id<T>::value,ret>::type#define WHEN_UNAVAILABLE_INLINE(id, ret) template<typename T> inline typename enable_if<!has_##id<T>::value,ret>::type#endif


// introspect.cpp with usage examples for the fast_swap case
#include <algorithm>#include <vector>#include <complex>#include "introspect.h"INTROSPECT(foo, void, swap, T);WHEN_UNAVAILABLE_INLINE(foo, void) fast_swap(T& a, T& b) {  ::std::swap<T>(a,b);}WHEN_AVAILABLE_INLINE(foo, void) fast_swap(T& a, T& b) {  a.swap(b);}int main() {   std::vector<int> vector1, vector2;   std::complex<int> complex1, complex2;   double a,b;   fast_swap(vector1, vector2);   fast_swap(complex1, complex2);   fast_swap(a,b);}


// Example of using the introspection to wrap cout: oswrapper.h
// The operator << is defined for the wrapper class to use an object's
// "void operator() (oswrapper&)" when it exists, and the usual operator <<
// for cout otherwise.
#ifndef OSWRAPPER_H#define OSWRAPPER_H// I can't do this by extending ostream, because I wouldn't be able to make a// wrapper representing cout...struct oswrapper {  ostream& x;  oswrapper(ostream& x) : x(x) {}  // For some reason, the free-function operator<<'s won't pick up endl etc.  oswrapper& operator<<(ostream& ( *pf )(ostream&));};extern oswrapper zout;#endif


// and oswrapper.cpp...
#include "introspect.h"#include "oswrapper.h"#include <iostream>using namespace std;oswrapper& oswrapper::operator<<(ostream& ( *pf )(ostream&)) {  x << pf;  return *this;}INTROSPECT_CONST(osf, void, operator(), oswrapper&);WHEN_UNAVAILABLE(osf, oswrapper&) operator<<(oswrapper& os, const T& thing) {  os.x << thing;  return os;}WHEN_AVAILABLE(osf, oswrapper&) operator<<(oswrapper& os, const T& thing) {  thing(os);  return os;}oswrapper zout(cout);


However, this doesn't really help with implementing the assignment operator for classes without a swap method, does it? :s

IMHO this is the truly nice thing about GCd languages - because of not worrying so much about when you need to delete something, you can avoid certain questions about pointer ownership, and not have to worry about the Rule of Three or equivalent - and you can share objects more often, because you aren't worried about double-deletion. If you really need to copy something in a "every object is a reference" language (Java/Python/etc. object model), you make a new copy, and just throw the old thing away. :)
Advertisement
Quote:Original post by mfawcett
Well, std::vector already specializes std::swap. It was mentioned earlier, but wouldn't the easiest thing be to just specialize std::swap on your type? That way the users can still just use std::swap like always, but it will just forward to your member swap.


The point of my code is that to get it to use the specialised version you don't rewrite the function, you specialise the traits structure. I think that isn't as tedious or error prone. Which is good for me as I am prone to errors and need all the help I can get.

Zahlman: wow.

edit: removed 'std::swap isn't specialised for std::vector' because I was wrong.

[Edited by - petewood on March 31, 2005 3:05:36 PM]
Quote:Original post by petewood
Quote:Original post by mfawcett
Well, std::vector already specializes std::swap. It was mentioned earlier, but wouldn't the easiest thing be to just specialize std::swap on your type? That way the users can still just use std::swap like always, but it will just forward to your member swap.


std::swap isn't specialised for std::vector.

The point of my code is that to get it to use the specialised version you don't rewrite the function, you specialise the traits structure. I think that isn't as tedious or error prone. Which is good for me as I am prone to errors and need all the help I can get.

Zahlman: wow.

You are probably right for your implementation. It is an implementation detail of Dinkumware I guess (not sure if any other STD library implentors did this because this is the only one I have installed). Here are the prototypes from my currently installed version:

void swap(vector& _Right);

friend void swap(vector<Type, Allocator >& _Left, vector<Type, Allocator >& Right);

I think I find this approach easier, although I'm in love with traits classes.

[Edited by - mfawcett on March 31, 2005 3:16:13 PM]
--Michael Fawcett
Quote:Original post by mfawcett
You are probably right for your implementation. It is an implementation detail of Dinkumware I guess (not sure if any other STD library implentators did this because this is the only one I have installed).

According to the C++ standard the following swap overloaded function exist in the namespace std.
namespace std {template <class T, class Allocator>void swap(vector<T,Allocator>& x, vector<T,Allocator>& y);}
Arguing on the internet is like running in the Special Olympics: Even if you win, you're still retarded.[How To Ask Questions|STL Programmer's Guide|Bjarne FAQ|C++ FAQ Lite|C++ Reference|MSDN]
Quote:Original post by dalleboy
Quote:Original post by mfawcett
You are probably right for your implementation. It is an implementation detail of Dinkumware I guess (not sure if any other STD library implentators did this because this is the only one I have installed).

According to the C++ standard the following swap overloaded function exist in the namespace std.


My bad. Sorry.
Quote:Original post by dalleboy
Quote:Original post by mfawcett
You are probably right for your implementation. It is an implementation detail of Dinkumware I guess (not sure if any other STD library implentors did this because this is the only one I have installed).

According to the C++ standard the following swap overloaded function exist in the namespace std.
namespace std {template <class T, class Allocator>void swap(vector<T,Allocator>& x, vector<T,Allocator>& y);}

Good find, thanks.
--Michael Fawcett

This topic is closed to new replies.

Advertisement