grive2/libgrive/src/util/Function.hh

185 lines
3.9 KiB
C++

/*
grive: an GPL program to sync a local directory with Google Drive
Copyright (C) 2012 Wan Wai Ho
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
#include <memory>
#include <utility>
namespace gr {
namespace impl
{
template <typename Type> class FuncImpl ;
template <typename R> class FuncImpl<R (void)>
{
public :
virtual R operator()( ) = 0 ;
virtual FuncImpl* Clone() const = 0 ;
virtual ~FuncImpl() {}
} ;
template <typename R, typename P1> class FuncImpl<R (P1)>
{
public :
virtual R operator()(P1) = 0 ;
virtual FuncImpl* Clone() const = 0 ;
virtual ~FuncImpl() {}
} ;
template <typename R, typename P1, typename P2> class FuncImpl<R (P1,P2)>
{
public :
virtual R operator()(P1,P2) = 0 ;
virtual FuncImpl* Clone() const = 0 ;
virtual ~FuncImpl() {}
} ;
template <typename Type>
struct FuncTrait ;
struct NullType {} ;
template <typename R> struct FuncTrait<R(void)>
{
typedef R ReturnType ;
typedef NullType Param1Type ;
typedef NullType Param2Type ;
} ;
template <typename R, typename P1> struct FuncTrait<R(P1)>
{
typedef R ReturnType ;
typedef P1 Param1Type ;
typedef NullType Param2Type ;
} ;
template <typename R, typename P1, typename P2> struct FuncTrait<R(P1,P2)>
{
typedef R ReturnType ;
typedef P1 Param1Type ;
typedef P2 Param2Type ;
} ;
template <class Type, typename F> class FuncHolder : public FuncImpl<Type>
{
public :
explicit FuncHolder( const F& f ) : m_func( f ) { }
FuncHolder* Clone() const { return new FuncHolder( *this ) ; }
typedef typename FuncTrait<Type>::ReturnType ReturnType ;
ReturnType operator()() { return m_func(); }
ReturnType operator()( typename FuncTrait<Type>::Param1Type p1)
{
return m_func(p1);
}
ReturnType operator()(
typename FuncTrait<Type>::Param1Type p1,
typename FuncTrait<Type>::Param2Type p2)
{
return m_func(p1,p2);
}
private :
F m_func ;
} ;
template <typename Type>
struct NullFunc
{
typedef typename FuncTrait<Type>::ReturnType ReturnType ;
ReturnType operator()()
{
return ReturnType() ;
}
ReturnType operator()( typename FuncTrait<Type>::Param1Type p1)
{
return ReturnType() ;
}
ReturnType operator()(
typename FuncTrait<Type>::Param1Type p1,
typename FuncTrait<Type>::Param2Type p2)
{
return ReturnType() ;
}
} ;
template <typename Type, typename F>
FuncHolder<Type,F>* MakeFuncHolder( F func )
{
return new FuncHolder<Type,F>( func ) ;
}
}
template <typename Type>
class Function
{
public :
Function( ) :
m_pimpl( impl::MakeFuncHolder<Type>( impl::NullFunc<Type>() ) )
{
}
Function( const Function& f ) :
m_pimpl( f.m_pimpl->Clone() )
{
}
template <typename F>
Function( const F& f ) :
m_pimpl( impl::MakeFuncHolder<Type>( f ) )
{
}
Function& operator=( const Function& f )
{
Function tmp( f ) ;
std::swap( m_pimpl, tmp.m_pimpl ) ;
return *this ;
}
~Function( )
{
}
typedef typename impl::FuncTrait<Type>::ReturnType ReturnType ;
ReturnType operator()( )
{
return (*m_pimpl)() ;
}
template <typename P1> ReturnType operator()( P1 p1 )
{
return (*m_pimpl)( p1 ) ;
}
template <typename P1, typename P2> ReturnType operator()( P1 p1, P2 p2 )
{
return (*m_pimpl)( p1, p2 ) ;
} ;
private :
typedef impl::FuncImpl<Type> Impl ;
std::unique_ptr<Impl> m_pimpl ;
} ;
} // end of namespace