I want to store a pair of member get/set functions for later use with an object of type T.
I have a partially working setup, see below. Questions remain however:
How do I (smartly) deal with all possible variants? member_get could be [returning value or const value& or even value& | const or non-const] member_set could be [accepting const &, & or &&]. Sure, 'best practices' would rule out some combinations, but I cannot rely on that as the definition of member_get and member_set is out of my hands.
How do I correctly deal with possible member_set move semantics?
Is there a different/better/simpler general way to approach this?
Notes:
- I intentionally left open the exact type S of the setter. Not sure if that's a good or bad idea.
- Lambdas obviously come to mind, but I can't see how they can help the issue. The caller of
Make( get, set )is not supposed to supply lambdas. That would be just delegating the problem to him!? - any std::function ideas should be ruled out because of the overhead
template <typename T, typename V, typename G, typename S>
class GetSet
{
public:
constexpr GetSet( G member_get, S member_set ) : Get( member_get ), Set( member_set )
{ }
auto GetValue( const T& t ) const
{
return ( t.*Get )( );
}
void SetValue( T& t, V&& value ) const
{
( t.*Set )( std::forward<V>( value ) );
}
private:
G Get;
S Set;
};
template <typename T, typename ValueType, typename S>
constexpr auto Make( ValueType( T::*member_get )( ) const, S member_set )
{
using G = ValueType( T::* )( ) const;
return GetSet<T, ValueType, G, S>( member_get, member_set );
}