簡體   English   中英

重載指向成員的指針 function 運算符。 嘗試解析 const 重載版本未編譯

[英]Overloading the pointer-to-member function operator. Attempting to resolving the const overloaded version isn't compiling

我目前正在練習 ->* 運算符,目的是編寫一個智能指針。 我已經了解了它的工作原理。 對於這個例子,我想在使用 operator->*() 時使用模板,因此我可以將成員函數用於各種返回和參數類型。

下面是我的目標的一個簡單例子

函子.h

    #pragma once
    #include "RecordCard.h"
    template <class OBJECT_TYPE, typename POINTER_TO_MEMBER>
    class Functor{
          public:
          Functor(OBJECT_TYPE* pObj, POINTER_TO_MEMBER pMF):m_pObj(pObj),m_pMF(pMF){}

          template <typename RETURN_TYPE>
          RETURN_TYPE operator() const
          {
              return (m_pObj->*m_pMF)();
          }

          template <typename PARAM_TYPE>
          void operator()(PARAM_TYPE param)
          {
              (m_pObj->*m_pMF)(param);
          }

         private:
             OBJECT_TYPE* m_pObj;
             POINTER_TO_MEMBER m_pMF;
    };

記錄卡.h

    #pragma once
    #include "Functor.h"
    #include <string>

    template <class T, typename U>
    class Functor;

    class RecordCard{
          public:
          RecordCard(){}
          void SetName(std::string);
          void SetAge(unsigned int);
          void SetActiveStatus(bool);
          std::string GetName() const;
          unsigned int GetAge() const;
          bool GetActiveStatus() const;
          // Other methods of the class

          template <typename T>
          Functor<RecordCard,T> operator->*(T pmf)
          {
              return Functor<RecordCard,T>(this, pmf);
          }

          template <typename T, typename U = T (RecordCard::*)() const>
          const Functor<RecordCard,U> operator->*(U pmf) const
          {
              return Functor<RecordCard,U>(this, pmf);
          }

         private:
             std::string m_szName;
             unsigned int m_nAge;
             bool m_bActive;
    };

記錄卡.cpp

    // Method definitions here
    // RecordCard::operator->* definition removed from her
    // and placed in the header file. Because to otherwise
    // causes the linker to complain.

現在問題出在我的主要。 主.cpp

    #include "RecordCard.h"
    #include "Functor.h"

    int main()
    {
         RecordCard mycard;
         (mycard->*&RecordCard::SetAge)(30);  // Works Okay
         (mycard->*&RecordCard::GetAge)(); Error??
         return 0;
    }

編譯器給我的兩個抱怨是:

找不到與 RecordCard::GetAge() const 匹配的簽名。

無法創建 Functor<RecordCard, int (RecordCard::*)()> 的實例

它發生的原因不是調用 operator->*() const。

在不使用 lambda 或 std::function 的情況下,這些是為了以后的練習。 如何解決這個問題,使其正常工作。

非常感謝。

你需要改變這個:

void operator(PARAM_TYPE param)

為此:

void operator()(PARAM_TYPE param)

附帶說明一下,在第一個operator()中,如果使用auto作為返回類型,則可以去掉模板:

auto operator() const
{
    return (m_pObj->*m_pMF)();
}

我意識到我哪里出了問題,當我發現是什么時踢了自己一腳。 問題是我忽略了 this 指針在 const 限定對象和非 const 對象之間的不同類型

舉個例子:

    #include <iostream>
    #include <typeinfo>
    class Foo{
          public:
          void describe_my_type() const
          {
              std::cout << typeid(this).name << std::endl;
          }

    };

    int main()
    {
          Foo foo1;
          const Foo foo2;
          foo1.describe_my_type(); // prints Foo*
          foo2.describe_my_type(); // prints const Foo*

          return 0;
    }

因此我想出了三種方法:

  1. 使用單個仿函數並以特定方式重載 function 調用運算符。
  2. 使用從公共基 class 派生的兩個仿函數類(一個用於 const 對象,另一個用於非 const 對象)。
  3. 使用包裝器 class 並讓它處理指向成員運算符和仿函數的指針

三者的共同點:

  • 仿函數是一個內部 class,它本身是外部 class 的公共對象
  • 仿函數將友誼授予其外部 class 以禁止外部實例。
  • 構造函數是私有的。
  • 添加 header 描述 class 方法的特征

方法特性.h

    // Base struct which has the common traits to avoid repetition 
    template <class O>
    struct MethodTraitsBase{
          using OBJECT = O;

    };

    // Primary template 
    template <typename T>
    struct MethodTraits;

    // Template specialisation 
    template <typename R, class O, typename... A>
    struct MethodTraits<R(O::*)(A...)>
    : MethodTraitsBase<O>{
    };

    template <typename R, class O, typename... A>
    struct MethodTraits<R(O::*)(A...) const>
    : MethodTraitsBase<O>{
    };

    template <typename R, class O, typename... A>
    struct MethodTraits<R(O::*)(A...) volatile>
    : MethodTraitsBase<O>{
    };

    template <typename R, class O, typename... A>
    struct MethodTraits<R(O::*)(A...) const volatile>
    : MethodTraitsBase<O>{
    };

方法一:單函子(RecordCard::Functor)

    #include "MethodTraits.h"
    class RecordCard{
          public:
          // As before

          template <typename T>
          class Functor{
              friend class RecordCard;
              typedef typename MethodTraits::OBJECT OBJECT_T;
          public:
              template <typename... U>
              auto operator() (U&& ...args)
              {
                  return (m_pObj->*m_pmf) (std::forward<U>(args)...);
              }

              template <typename... V>
              auto operator() (V&& ...args) const
              {
                  if (m_pmf)
                      return (m_pObj->*m_pmf) (std::forward<V>(args)...);
                  else
                      return (m_pcObj->*m_pmf) (std::forward<V>(args)...);
              }

          private:

              Functor(OBJECT_T* pObj, T pmf)
              : m_pObj(pObj), m_pmf(pmf), m_pcObj(nullptr)
              {}

              Functor(const OBJECT_T* pcObj, T pmf)
              : m_pObj(nullptr), m_pmf(pmf), m_pcObj(pcObj)
              {}

              // deleted to prevent unauthorised crfeations
              // copies and transfers
              Functor() = delete;
              Functor(const Functor&) = delete;
              Functor& operator=(const Functor&) = delete;
              Functor& operator=(Functor&&) = delete;

              // C++17 this can be marked as delete too due to copy elision

              // C++11/14 this needs unmarked as it invokes move semantics
              Functor(Functor&&);
              OBJECT_T* m_pObj;
              const OBJECT_T* m_pcObj;
              T m_pmf;

          };

          template <typename W>
          Functor<W> operator->*(W pmf)
          {
              return Functor<W>(this, pmf);
          }

          template <typename X>
          Functor<X> operator->*(X pmf) const
          {
              return Functor<X>(this, pmf);
          }

         private:
             // as before
    };

方法二:從公共基類型 (RecordCard::FunctorBase) 派生的兩個仿函數

    class RecordCard{
          public:
          // As before

          template <typename T>
          class FunctorBase{
              // All members protected access
          protected:
              typedef typename MethodTraits::OBJECT OBJECT_T;
              FunctorBase(T pmf)
              : m_pmf(pmf)
              {}
              // Delete other constructors except the move ctor 
              T m_pmf;

          };

          template <typename T>
          class NonConstFunctor : public FunctorBase<T>{
              friend class RecordCard;
          public:
              template <typename... U>
              auto operator() (U&& ...args)
              {
                  return (m_pObj->*m_pmf) (std::forward<U>(args)...);
              }

          private:

              Functor(OBJECT_T* pObj, T pmf)
              : FunctorBase(pmf), m_pObj(pObj)
              {}

              {}

              // No need to mark ctors as deleted as base class does that
              // Therefore compiler will complain
              OBJECT_T* m_pObj;

          };

          template <typename T>
          class NonConstFunctor : public FunctorBase<T>{
              friend class RecordCard;
          public:
              template <typename... V>
              auto operator() (V&& ...args) const
              {
                  return (m_pObj->*m_pmf) (std::forward<V>(args)...);
              }

          private:

              Functor(const OBJECT_T* pcObj, T pmf)
              : FunctorBase(pmf), m_pcObj(pObj)
              {}

              {}

              const OBJECT_T* m_pcObj;

          };

          template <typename W>
          NonConstFunctor<W> operator->*(W pmf)
          {
              return NonConstFunctor<W>(this, pmf);
          }

          template <typename X>
          ConstFunctor<X> operator->*(X pmf) const
          {
              return ConstFunctor<X>(this, pmf);
          }

         private:
             // as before
    };

方法三:包裝器 class 和單個函子

    #include "MethodTraits.h"
    template <class T>
    class PointerWrapper{
          public:
          PointerWrapper(T* ptr)
          : m_ptr(ptr)
          {}

          template <typename U>
          class Functor{
              friend class PointerWrapper<T>;
              typedef typename MethodTraits::OBJECT OBJECT_T;
          public:
              // code to overload the function call operator
          private:

              // Two paramaters ctor
              // Deleted ctors
              // Two members



          };


          template <typename X>
          Functor<X> operator->*(X pmf) const
          {
              return Functor<X>(m_ptr, pmf);
          }

         private:
             T* m_ptr
    };

它可以這樣實現:

    RecordCard rc;
    PointerWrapper<RecordCard> wrapper(&rc);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM