如何解决存储成员的获取/设置功能以供以后使用
我想存储一对成员get / set函数,以便以后与T类型的对象一起使用。
我有部分工作设置,请参见下文。问题仍然存在:
-
我如何(智能)处理所有可能的变体? member_get可能是[返回值或const值&甚至是value&| const或非const] member_set可以是[接受const&,&或&&]。当然,“最佳实践”会排除某些组合,但是我不能依靠它,因为对member_get和member_set的定义已不复存在。
-
我如何正确处理可能的member_set移动语义?
注意:
- 我特意留下了二传手的确切类型S。不知道这是个好主意。
- Lambda很明显浮现在脑海中,但我看不到它们如何帮助解决这个问题。
Make( get,set )
的调用方不应该提供lambda。那只是将问题委托给他!? - 由于开销太大,应该排除所有std :: function想法
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 );
}
解决方法
不确定为什么需要这样做,但是最简单的解决方案如下。
#include <utility>
template <class F> struct ClassType;
template <typename Ret,typename TCls,typename... Args>
struct ClassType<Ret (TCls::*)(Args...)> {
using type = TCls;
};
template <typename Ret,typename TCls>
struct ClassType<Ret (TCls::*)() const> {
using type = TCls;
};
template<class TFnGet,class TFnSet>
class GetSet
{
public:
using TGet = TFnGet;
using TSet = TFnSet;
public:
inline GetSet(TGet fnGet,TSet fnSet)
: m_fnGet(fnGet),m_fnSet(fnSet)
{
}
template<class T>
inline decltype(auto) GetValue(T&& r) const
{
static_assert(std::is_same<typename std::remove_cv<typename std::remove_reference<T>::type>::type,typename ClassType<TFnGet>::type>::value,"wrong type of r?");
return (r.*m_fnGet)();
}
template<class T,class TValue>
inline void SetValue(T&& r,TValue&& value)
{
static_assert(std::is_same<typename std::remove_cv<typename std::remove_reference<T>::type>::type,typename ClassType<TFnSet>::type>::value,"wrong type of r?");
(r.*m_fnSet)(std::forward<TValue>(value));
}
private:
TGet m_fnGet;
TSet m_fnSet;
};
template<class TGet,class TSet>
GetSet<TGet,TSet> MakeGetSet(TGet fnGet,TSet fnSet)
{
static_assert(std::is_same<typename ClassType<TGet>::type,typename ClassType<TSet>::type>::value,"members of different classes?");
return GetSet<TGet,TSet>(fnGet,fnSet);
}
已验证:
class A
{
public:
void Set(int i) {}
int Get() const { return 0;}
void SetRef(char& ch) {}
A& GetRef() { return *this;}
void SetRRef(float&& ) {}
int&& GetRRef() { return 1; }
void SetConstRef(const char& ch) {}
int GetNotConst() { return 0;}
};
int main(int argc,char* argv[])
{
A a;
auto gs = MakeGetSet(&A::Get,&A::Set);
auto gsRef = MakeGetSet(&A::GetRef,&A::SetRef);
auto gs2 = MakeGetSet(&A::GetRRef,&A::SetRRef);
auto gsNonConst = MakeGetSet(&A::GetNotConst,&A::SetConstRef);
int x = gs.GetValue(a);
gs.SetValue(a,2);
const A& ra = a;
x = gs.GetValue(ra);
A& r = gsRef.GetValue(a);
char ch =' ';
gsRef.SetValue(a,ch);
x = gs2.GetValue(a);
gs2.SetValue(a,1.1f);
x = gsNonConst.GetValue(a);
gsNonConst.SetValue(a,ch);
std::cout << "ok\n";
return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。