Skip to content
Snippets Groups Projects
Commit ad44c1d4 authored by Jan Trávníček's avatar Jan Trávníček
Browse files

move has_clone to traits, + copy_move template

parent d7fd1d9a
No related branches found
No related tags found
No related merge requests found
...@@ -10,16 +10,6 @@ ...@@ -10,16 +10,6 @@
   
namespace std { namespace std {
   
template<class T> struct has_clone {
typedef char (&Yes)[1];
typedef char (&No)[2];
template<class U>
static Yes test(U * data, typename std::enable_if< std::is_pointer<decltype(data->clone())>::value>::type * = 0);
static No test(...);
static const bool value = sizeof(Yes) == sizeof(has_clone::test((typename std::remove_reference<T>::type*)0));
};
template<class T, typename std::enable_if< ! std::has_clone<T>::value >::type* = nullptr> template<class T, typename std::enable_if< ! std::has_clone<T>::value >::type* = nullptr>
T* clone(const T * const tmp) { T* clone(const T * const tmp) {
return new T(*tmp); return new T(*tmp);
......
...@@ -12,6 +12,17 @@ ...@@ -12,6 +12,17 @@
   
namespace std { namespace std {
   
template<class T>
struct has_clone {
typedef char (&Yes)[1];
typedef char (&No)[2];
template<class U>
static Yes test(U * data, typename std::enable_if< std::is_pointer<decltype(data->clone())>::value>::type * = 0);
static No test(...);
static const bool value = sizeof(Yes) == sizeof(has_clone::test((typename std::remove_reference<T>::type*)0));
};
template <typename T> template <typename T>
struct is_base_of<T, T> { struct is_base_of<T, T> {
static const bool value = true; static const bool value = true;
......
...@@ -10,6 +10,30 @@ ...@@ -10,6 +10,30 @@
   
namespace std { namespace std {
   
template < class T, typename std::enable_if < ! std::has_clone < T >::value >::type * = nullptr >
inline T copy_move ( const T & param ) {
return T ( param );
}
template < class T >
struct implicit_cast {
T * holder;
~implicit_cast ( ) {
delete holder;
}
operator T && ( ) {
return std::move ( * holder );
}
};
template < class T, typename std::enable_if < std::has_clone < T >::value >::type * = nullptr >
inline implicit_cast < T > copy_move ( const T & param ) {
return implicit_cast < T > { param.clone ( ) };
}
// TODO remove after switching to c++17 (as_const)
template < class T > template < class T >
inline const T & make_const ( T & ptr ) { inline const T & make_const ( T & ptr ) {
return static_cast < const T & > ( ptr ); return static_cast < const T & > ( ptr );
......
#include "ParamPassTest.h"
#include <exception>
#include <utility>
#include <memory>
#include <type_traits>
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( ParamPassTest, "bits" );
CPPUNIT_TEST_SUITE_REGISTRATION ( ParamPassTest );
void ParamPassTest::setUp ( ) {
}
void ParamPassTest::tearDown ( ) {
}
int instances = 0;
class FooCloneable {
int data;
FooCloneable ( const FooCloneable & foo ) : data ( foo.data ) {
std::cout << "Copy" << std::endl;
instances++;
}
FooCloneable ( FooCloneable && foo ) : data ( foo.data ) {
std::cout << "Move" << std::endl;
instances++;
}
public:
FooCloneable ( int data ) : data ( data ) {
std::cout << "Constructor" << std::endl;
instances++;
}
~FooCloneable ( ) {
std::cout << "Destructor" << std::endl;
instances--;
}
FooCloneable * clone ( ) const {
return new FooCloneable ( * this );
}
int getData ( ) const {
return data;
}
};
class FooCopyable {
int data;
public:
FooCopyable ( int data ) : data ( data ) {
std::cout << "Constructor" << std::endl;
instances++;
}
FooCopyable ( const FooCopyable & foo ) : data ( foo.data ) {
std::cout << "Copy" << std::endl;
instances++;
}
FooCopyable ( FooCopyable && foo ) : data ( foo.data ) {
std::cout << "Move" << std::endl;
instances++;
}
~FooCopyable ( ) {
std::cout << "Destructor" << std::endl;
instances--;
}
FooCopyable * clone ( ) const {
return new FooCopyable ( * this );
}
int getData ( ) const {
return data;
}
};
int dest ( FooCloneable && foo ) {
std::cout << "Destination called" << std::endl;
if ( instances < 2 )
throw std::exception ( );
return foo.getData ( );
}
int dest ( FooCopyable && foo ) {
std::cout << "Destination called" << std::endl;
if ( instances < 2 )
throw std::exception ( );
return foo.getData ( );
}
int test ( FooCloneable && foo ) {
return dest ( std::move ( foo ) );
}
int test ( const FooCloneable & foo ) {
return test ( std::copy_move ( foo ) );
}
int test ( FooCopyable && foo ) {
return dest ( std::move ( foo ) );
}
int test ( const FooCopyable & foo ) {
return test ( std::copy_move ( foo ) );
}
void ParamPassTest::testParameterPassing ( ) {
{
const FooCloneable foo ( 1 );
int res = 0;
CPPUNIT_ASSERT_NO_THROW ( res = test ( foo ) );
CPPUNIT_ASSERT ( res == 1 && instances == 1 );
}
{
const FooCopyable foo ( 1 );
int res = 0;
CPPUNIT_ASSERT_NO_THROW ( res = test ( foo ) );
CPPUNIT_ASSERT ( res == 1 && instances == 1 );
}
}
#ifndef PARAM_PASS_TEST_H_
#define PARAM_PASS_TEST_H_
#include <cppunit/extensions/HelperMacros.h>
class ParamPassTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE ( ParamPassTest );
CPPUNIT_TEST ( testParameterPassing );
CPPUNIT_TEST_SUITE_END ( );
public:
void setUp ( );
void tearDown ( );
void testParameterPassing ( );
};
#endif // PARAM_PASS_TEST_H_
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment