[英]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;
}
因此我想出了三種方法:
三者的共同點:
方法特性.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.