c++ - 存储成员 get/set 函数供以后使用

标签 c++ templates member-function-pointers member-functions

我想存储一对成员 get/set 函数以供以后与 T 类型的对象一起使用。
我有一个部分工作的设置,见下文。然而问题仍然存在:

  • 我如何(聪明地)处理所有可能的变体? member_get 可以是 [returning value or const value& 甚至 value& | const or non-const] member_set 可以是 [接受 const &, & 或 &&]。当然,“最佳实践”会排除某些组合,但我不能依赖它,因为 member_get 和 member_set 的定义不在我的掌控之中。
  • 如何正确处理可能的 member_set 移动语义?
  • 有没有不同/更好/更简单的通用方法来解决这个问题?

  • 笔记:
  • 我故意让 setter 的确切类型 S 保持打开状态。不确定这是个好主意还是坏主意。
  • 显然我想到了 Lambda,但我看不出它们如何解决这个问题。 Make( get, set )的来电者不应该提供 lambdas。那就是把问题委托(delegate)给他!?
  • 由于开销
  • ,应排除任何 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;
    }
    

    关于c++ - 存储成员 get/set 函数供以后使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63614100/

    相关文章:

    c++ - C++将类方法作为函数指针传递

    c++ - 创建用户在 C++ 中定义的星星对角线

    c++ - QPainter性能高帧率

    c++ - 使用模板进行参数转换出错

    C++ 在模板类中重载运算符<<

    c++ - 在 C++ 中,模板在我专门化时是否实例化了?

    c++ - C++ 14或C++ 1z是否已经或将不再不确定以调用委托(delegate)类成员函数指针?

    C++:在函数指针 vector 中存储和调用函数指针

    c++ - 是否可以强制Linux在释放后使虚拟内存失效

    c++ - 错误 - : 'QObject::QObject' : cannot access private member declared in class 'QObject'