如何使用代理 class 和模板将 "simulate" 函数重载 return 值?

How to use proxy class and template to "simulate" function overload by return value?

我会尝试挖掘更多的 C++ 模板和类型系统知识,我知道通过重载 Type.Operator(),它看起来像 "overload" 由 return 类型,

#include<iostream>
using namespace std;
class My{
    int getInt() const {return 20;}
    short getShort() const {return 3;}
public:
    template<class T>
    T get() const

    template<int>
    int get() const {return getInt();}

    template<short>
    short get() const {return getShort();}
};
struct Proxy{
    My const* myOwner;
    Proxy(My const* owner):myOwner(owner){}
    operator int() const {return myOwner->getInt();}
    operator short() const {return myOwner->getShort();}
};
int main(){
    My m;
    Proxy p(&m);
    int _i = p;//works!
    short _s = p;//works!
    cout<<_i<<","<<_s<<",\n";

    // How to use template My::get
    int i = m.get(); // doesn't compile
    short s = m.get(); // doesn't compile
    cout<<i<<","<<s<<",\n";
    return 0;
}

我希望有一些方法可以使下面几行根据 return 类型进行不同的函数调用:

int i = m.get();
short s = m.get();

如何实现?非常感谢。

您可以像这样使用 SFINAE:

template <typename T,
          typename std::enable_if<std::is_same<T, int>::value>::type* = nullptr>
int get() const {
    return getInt();
}

template <typename T,
          typename std::enable_if<std::is_same<T, short>::value>::type* = nullptr>
short get() const {
    return getShort();
}

然后在Proxy class中调用上面的函数如:

operator int() const {
    return myOwner->get<int>();
}
operator short() const {
    return myOwner->get<short>();
}

在主函数中:

int i = m.get<int>();
short s = m.get<short>();

Demo

注意:函数 return 值被分配给 intshort 的事实未在模板中使用参数扣除.

... to "simulate" function overload by return value?

忽略示例的所有样板文件并只关注这个问题,您可以定义一个主模板函数并删除(主模板)定义,然后添加显式(完整) 此函数的特化仅适用于您想要 "overload":

的类型
#include <cstdint>

template <typename T>
T get() = delete;

template<>
uint8_t get<uint8_t>() { return 42U; }  // or delegate to getUint8().

template<>
uint32_t get<uint32_t>() { return 43U; }

template<>
float get<float>() { return 44.5F; }

int main() {
    const auto a = get<uint8_t>();
    const auto b = get<uint32_t>();
    const auto c = get<float>();
    // const auto d = get<uint16_t>(); // error: use of deleted function
}

但是请注意,您需要明确指定单一类型模板参数的类型,因为没有 get() 的参数可用于模板参数推导。

如果我理解您的目标,那么您的实现(以及其他必要的修复)中缺少的是 My 的成员函数,它实际上 returns 一个 Proxy.

类似于以下内容(可测试 here

#include<iostream>

class Proxy;

class My
{
public:
    template<class T = Proxy>  // <--
    T get() const;
};

class Proxy
{
    My const& owner_;
public:
    Proxy(My const& owner) : owner_(owner)
    {}
    operator int() const;
    operator short() const;
};

template<>
Proxy My::get<Proxy>() const {
    return *this;              // <--- 
}

template<>
int My::get<int>() const {
    return 20;
}

template<>
short My::get<short>() const {
    return -3;
}

Proxy::operator int() const {
    return owner_.get<int>();
}
Proxy::operator short() const {
    return owner_.get<short>();
}

int main()
{
    My m;
    int i = m.get<int>();
    short s = m.get<short>();
    std::cout << i << ", " << s << '\n';

    int i_ = m.get();
    short s_ = m.get();
    std::cout << i_ << ", " << s_ << '\n';
}