int main( void ){
using namespace my_ref_impl;
int var { 5 };
auto var_const_ref = cref< int >( var );
// static_assert( std::is_const< decltype( var_const_ref.get() ) >::value, "var_const_ref has underlying const ref" );
auto var_ref = ref< int >( var );
std::cout << "var before:\t" << var << '\n';
var_ref.get() = 3;
std::cout << "var after:\t" << var << '\n';
auto func = []{ puts("func called..."); };
auto fcref = cref< decltype( func ) >( func );
fcref();
return 0;
}
#include <memory>
#include <type_traits>
#include <utility>
#include <functional>
#include <iostream>
#include <span>
namespace my_ref_impl{
template < typename _Tp >
class reference_wrapper{
_Tp *_M_data;
constexpr static _Tp* _S_fun( _Tp& __r ) noexcept
{ return std::addressof( __r ); }
static void _S_fun( _Tp&& ) = delete;
template < typename _Up, typename _Up2 = std::remove_cv< std::decay_t< _Up > >::type >
using __not_same
= typename std::enable_if< !std::is_same< reference_wrapper, _Up2 >::value >::type;
public:
typedef _Tp type;
template < typename _Up,
typename = __not_same< _Up >,
typename = decltype( reference_wrapper::_S_fun( std::declval< _Up >() ) ) >
constexpr
reference_wrapper( _Up&& __uref )
noexcept( noexcept( reference_wrapper::_S_fun( std::declval< _Up >() ) ) )
: _M_data( reference_wrapper::_S_fun( std::forward< _Up >( __uref ) ) ) { }
reference_wrapper( const reference_wrapper& ) = default;
reference_wrapper& operator=( const reference_wrapper& ) = default;
constexpr _Tp&
get( void ) const noexcept
{return *_M_data; }
constexpr
operator _Tp&( void ) const noexcept
{ return this->get(); }
template < typename..._Args >
constexpr
typename std::result_of< _Tp&( _Args&&... ) >::type
operator()( _Args&&...__args ) const{
if constexpr ( std::is_object< type >::value )
static_assert( sizeof( type ), "type must be complete" );
return std::invoke( get(), std::forward< _Args >( __args )... );
}
};
template < typename _Tp >
reference_wrapper( _Tp& )
->reference_wrapper< _Tp >;
template < typename _Tp >
inline reference_wrapper< _Tp >
ref( reference_wrapper< _Tp > __t )
noexcept
{ return __t; }
template < typename _Tp >
inline reference_wrapper< const _Tp >
cref( reference_wrapper< _Tp > __t )
noexcept
{ return __t.get(); }
};