重载 C++函数映射容器中的函数返回类型:自动推导失败并出现编译器错误

发布于 2024-12-21 02:55:26 字数 2593 浏览 1 评论 0原文

我有像 this 这样的简单类(其行为类似于 Boost::overload,但其中有命名函数(我用它来简化\缩小反射\内省目的))。输入参数的多个返回类型存在问题(编译器错误 3066)。我的代码:

#include <iostream>
#include <string>
#include <map>
#include <vector>

template < class T0, class T1 >
class my_map {
    typedef T0 type_0;
    typedef T1 type_1;
    std::map < std::string, type_0 * >T0_var;
    std::map < std::string, type_1 * >T1_var;
    friend class apitemp;
public:
    my_map(int meaningless0 = 42, int meaningless1 = 42) {} 
    class apitemp {
        std::string n_;
        my_map *p;
    public: 
        apitemp(std::string name_, my_map * parent):n_(name_), p(parent) {}
        operator  type_0 *() {
            return p->T0_var[n_];
        }
        operator  type_1 *() {
            return p->T1_var[n_];
        }
    };
    void insert(std::string name, type_0 * ptr) {
       T0_var[name] = ptr;
    }
    void insert(std::string name, type_1 * ptr) {
       T1_var[name] = ptr;
    }
    apitemp operator[] (std::string n_) {
       return apitemp(n_, this);
    }
};

template<class out, class in1, class in2>
    out hello_world(in1 name, in2 number )
{
    name += "!";
    std::cout << "Hello, " << name << std::endl;
    return number;
}

template<class in1, class in2>
std::string hello_world(in1 name, in2 number )
{
    name += "!";
    std::cout << "Hello, " << name << std::endl;
    return std::string("Yep, we can!");
}

int main() {
    int a =  hello_world<int, std::string, const int &>("Tim", 25);
    std::string b = hello_world<std::string, const int &>("Tim", 25);

    my_map<int(std::string, const int &), std::string(std::string, const int &)> myMap;
    myMap.insert("my_method_hello", &hello_world<int, std::string, const int &> ); 
    myMap.insert("my_method_hello2", &hello_world<std::string, const int &> ); 
    //int a = myMap["my_method_hello"]("Tim", 25); // error C3066: there are multiple ways that an object of this type can be called with these arguments
    //std::string b = myMap["my_method_hello2"]("Tim", 25); // // error C3066: there are multiple ways that an object of this type can be called with these arguments

    std::cin.get();
}

如何向其API引入多个返回类型函数? API用户是否可以以不可见的方式实现?或者至少有一些让 API 用户感到不安的东西,比如

int a = myMap["my_method_hello"]("Tim", 25)::int; 
std::string b = myMap["my_method_hello2"]("Tim", 25)::string;

I have simple class like this (which behaves like Boost::overload, but has named functions in it ( I use it for simplified\minified reflection\introspection purposes) ). It has problems with multiple return types for input arguments (compiler error 3066). My code:

#include <iostream>
#include <string>
#include <map>
#include <vector>

template < class T0, class T1 >
class my_map {
    typedef T0 type_0;
    typedef T1 type_1;
    std::map < std::string, type_0 * >T0_var;
    std::map < std::string, type_1 * >T1_var;
    friend class apitemp;
public:
    my_map(int meaningless0 = 42, int meaningless1 = 42) {} 
    class apitemp {
        std::string n_;
        my_map *p;
    public: 
        apitemp(std::string name_, my_map * parent):n_(name_), p(parent) {}
        operator  type_0 *() {
            return p->T0_var[n_];
        }
        operator  type_1 *() {
            return p->T1_var[n_];
        }
    };
    void insert(std::string name, type_0 * ptr) {
       T0_var[name] = ptr;
    }
    void insert(std::string name, type_1 * ptr) {
       T1_var[name] = ptr;
    }
    apitemp operator[] (std::string n_) {
       return apitemp(n_, this);
    }
};

template<class out, class in1, class in2>
    out hello_world(in1 name, in2 number )
{
    name += "!";
    std::cout << "Hello, " << name << std::endl;
    return number;
}

template<class in1, class in2>
std::string hello_world(in1 name, in2 number )
{
    name += "!";
    std::cout << "Hello, " << name << std::endl;
    return std::string("Yep, we can!");
}

int main() {
    int a =  hello_world<int, std::string, const int &>("Tim", 25);
    std::string b = hello_world<std::string, const int &>("Tim", 25);

    my_map<int(std::string, const int &), std::string(std::string, const int &)> myMap;
    myMap.insert("my_method_hello", &hello_world<int, std::string, const int &> ); 
    myMap.insert("my_method_hello2", &hello_world<std::string, const int &> ); 
    //int a = myMap["my_method_hello"]("Tim", 25); // error C3066: there are multiple ways that an object of this type can be called with these arguments
    //std::string b = myMap["my_method_hello2"]("Tim", 25); // // error C3066: there are multiple ways that an object of this type can be called with these arguments

    std::cin.get();
}

How to introduce to its API multiple return type functions? Is it possible in invisiable for API user way? Or at least with something API user disturbing like

int a = myMap["my_method_hello"]("Tim", 25)::int; 
std::string b = myMap["my_method_hello2"]("Tim", 25)::string;

?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

萌面超妹 2024-12-28 02:55:26

一种方法是让 myMap["my_method_hello"]("Tim", 25) 返回一个定义 operator int(), operator 的代理对象std::string() 等您希望它返回的每种类型。另一种方法是让代理对象为每种类型定义显式的 .asInt().asString() 方法。

如果目标类型在源代码中不明确(例如,如果将结果传递给函数),则重载运算符技术可能会令人困惑。同样,代理类型可能会混淆您传递给它的模板函数,并且如果候选集包含同时采用 intstd 的函数,则将无法轻松选择重载函数: :string (或代理自动转换为的其他类型。因此,除了任何运算符之外,我建议提供 .asInt() 等函数。

您还可以拼写 .asInt() 等像 templateas() 这样的函数并使用显式专门化来定义新的转换,唯一的缺点是源代码变得有点难以阅读。

One way to do this is to have myMap["my_method_hello"]("Tim", 25) return a proxy object that defines operator int(), operator std::string(), etc for each type you want it to return. Another way is to have the proxy object define explicit .asInt(), .asString() methods for each type.

The overloaded operator technique can get confusing if the target type isn't explicit in the source code (for example, if you're passing the result to a function). Similarly, the proxy type is likely to confuse template functions you pass it to, and won't be able to easily select an overloaded function if the candidate set includes functions taking both int and std::string (or other types the proxy auto-converts to. So I recommend providing the .asInt(), etc. functions in addition to any operators.

You can also spell the .asInt(), etc. functions like template<typename T> as() and use explicit specialization to define new conversions. The only downside to this is that the source code gets a bit harder to read.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文