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

时间:2011-12-15 07:45:49

标签: c++ templates compiler-errors overloading return-type

我有类似this的简单类(其行为类似于Boost :: overload,但在其中已命名函数(我将其用于简化\ minified反射\内省目的))。输入参数的多个返回类型存在问题(编译器错误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;

1 个答案:

答案 0 :(得分:3)

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

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

您还可以拼写.asInt()等函数,例如template<typename T> as(),并使用显式特化来定义新的转化。唯一的缺点是源代码有点难以阅读。