// ------------------------------------------------------------------------
/*
	author: Jaap Suter
   
	Copyright (C) Electronic Arts Canada Inc. 2002.  All rights reserved.	
*/
// ------------------------------------------------------------------------

/*! \file */

#ifndef REVEAL_CALLBACK_ASSIGN_TO_REF_ADAPTER_H
#define REVEAL_CALLBACK_ASSIGN_TO_REF_ADAPTER_H

#include "reveal/callback/callback_1.h"

namespace Reveal {
    namespace Callback {

// Forward;
template < class T > class AssignToRefAdapterFunctor;

// ------------------------------------------------------------------------
/*!
    \brief Constructs an assigning-callback from a reference;

    \param T    Parameter type of the reference;

    This allows us to create a callback that does nothing but assign the 
    incoming variable directly to a stored reference. This way people 
    don't have to write wrapper functions that only set a variable directly.

    The callback has to be from T to void, and the usage will be like:
    \code
        someType a = 2;
        someType b = 3;
        Callback< void, someType > callback = AssignToRefAdapter( a );
        callback( b );
        assert( a == 3 );
    \endcode
*/
// ------------------------------------------------------------------------
template < class T >
Callback1< void, T > AssignToRefAdapter( T& param )
{
	return Callback1< void, T >( AssignToRefAdapterFunctor< T >( param ) );
}

// ------------------------------------------------------------------------
/*!
    \brief Only used internally, see the \a AssignToRefAdapter function for 
		   the wrapper
    
	\remark	There is a wrapper function around this class for the following reasons:
				- Ease of use because functions don't require explicit template
				   parameters, so we can let the compiler derive them.
			    - It solves an issue with the compiler (correctly) parsing a statement 
				  as a function instead of an instantiation. See Effective STL Item 8 
				  for a description of a similar problem. 
			
	\remark	The standard library function std::bind1st uses the same idiom (the 
			named constructor idiom) as a wrapper around std::binder1st, for 
			(among others) the same reasons.

	\internal
*/
// ------------------------------------------------------------------------
template < class T >
class AssignToRefAdapterFunctor
{
    // Default copy ctor is ok, assigment operator is disabled (references can't be reseated);
	AssignToRefAdapterFunctor& operator = ( const AssignToRefAdapterFunctor& );

private:
    friend Callback1< void, T > AssignToRefAdapter< T >( T& param );
    
    // Private because only the friend can construct this;
    explicit AssignToRefAdapterFunctor( T& variable ) : mVariable( variable ) {}

public:
       
    void operator () ( T param ) { mVariable = param; }

private:

	T& mVariable;
};


    } // Namespace Callback;
} // Namespace Reveal;

#endif
