如何在不添加/删除mem函数的const常数的情况下重载getter函数?

时间:2019-05-23 14:19:26

标签: c++ overloading c++17 member-functions

我不知道为什么,为什么C ++不允许根据返回类型进行重载,如以下情况 三个成员(getter)函数具有不同的函数签名,甚至在存储时 指向成员函数的指针,我们需要不同的内存函数指针类型,例如:

for instance T = std::string
using constRefPtr   = const std::string&(MyStruct::*)() const;
using constValuePtr = const std::string(MyStruct::*)() const;
using valuePtr      = std::string(MyStruct::*)() const;

我已经读过这个similar post,在这里建议使用const和非成本 成员函数。

问题:如何在不消除const ness的情况下使以下(getter)重载工作 每个成员函数(如果可以通过标准C ++实现)?

我正在使用C ++ 17。

#include <iostream>
#include <string>

template<typename T> class MyStruct
{
    T m_val;
public: 
    explicit MyStruct(const T& value) 
        : m_val(value)
    {}
    const T& getVal() const {   return m_val; } // get val as const ref(no copy of member)
    const T getVal() const  {   return m_val; } // get a const member as return
    T getVal() const        {   return m_val; } // get a copy of member
};

int main()
{
    MyStruct<std::string> obj{"string"};
    const auto& val_const_ref = obj.getVal();  // overload const std::string& getVal() const
    const auto val_const = obj.getVal();       // overload const std::string getVal()  const
    auto val = obj.getVal();                   // overload std::string getVal()  const
    return 0;
}

我收到的错误消息:

error C2373 : 'MyStruct<T>::getVal' : redefinition; different type modifiers
note: see declaration of 'MyStruct<T>::getVal'
note: see reference to class template instantiation 'MyStruct<T>' being compiled
error C2059 : syntax error : 'return'
error C2238 : unexpected token(s) preceding ';'
error C2143 : syntax error : missing ';' before '}'
error C2556 : 'const T MyStruct<T>::getVal(void) const' : overloaded function differs only by return type from 'const T &MyStruct<T>::getVal(void) const'
1 > with
1 > [
    1 > T = std::string
        1 > ]
    1 > C:\Z Drive\CPP Programs\Visual Studio Project\Main.cc(62) : note: see declaration of 'MyStruct<std::string>::getVal'
note: see reference to class template instantiation 'MyStruct<std::string>' being compiled
error C2373 : 'MyStruct<std::string>::getVal' : redefinition; different type modifiers
note: see declaration of 'MyStruct<std::string>::getVal'
error C2059 : syntax error : 'return'
error C2238 : unexpected token(s) preceding ';'
error C2146 : syntax error : missing ';' before identifier 'T'
error C2530 : 'val_const_ref' : references must be initialized
error C2789 : 'val_const' : an object of const - qualified type must be initialized
note: see declaration of 'val_const'

3 个答案:

答案 0 :(得分:4)

您只是……不能在返回类型,句号止损过载。

您可以创建两个名称不同的函数:

T const& ref() const { return m_val; }
T val() const        { return m_val; }

根据const&的性,哪些自身可以重载:

T const& ref() const { return m_val; }
T&       ref()       { return m_val; }

T val() const&       { return m_val; }
T val() &&           { return std::move(m_val); }

答案 1 :(得分:2)

不可能。您不能在返回类型上重载。重载解析考虑了功能签名。函数签名由以下组成:

  • 功能名称
  • cv限定词
  • 参数类型

标准说:

1.3.11签名

  

有关参与重载的函数的信息   分辨率(13.3):其参数类型列表(8.3.5),以及   函数是一个类成员,函数上的cv限定词(如果有)   本身以及声明成员函数的类。 [...]

(从Luchian Grigore's answer进行了轻松编辑)

答案 2 :(得分:0)

  

问题:如何在不删除每个成员函数的常量性的情况下使以下(getter)重载工作(如果可以通过标准C ++实现)?

适当命名。正如@Slava指出的那样,当返回复制的值时,没有区别Tconst T的意义,所以类似:

const T& getConstRefVal() const { return m_val; } // get val as const ref(no copy of member)
T        getVal()         const { return m_val; } // get a copy of member