如何让标签调度与字符串一起使用?

时间:2013-01-30 02:33:55

标签: c++ templates c++11

我需要帮助让此代码的已损坏部分正常工作。

如何根据字符串标记调度两个函数(返回不同的值类型)?

如果可以简化整体代码以调度字符串,请提出建议。 TY。

要求:

  1. 基于字符串发送
  2. Rectangle重载需要返回int,而Circle重载需要返回std :: string
  3. 从Rectangle_Type到int和Circle_Type到std :: string的映射是固定的,并且在编译时是已知的。我的部分问题是std :: map是一个运行时构造:我不知道如何使std :: string标记映射编译时构造。
  4. 如果需要,运行时解析是可以的:但是,调度必须允许基于解析为的枚举/类型的不同返回类型。
  5. CODE

    #include <map>
    #include <string>
    #include <iostream>
    
    struct Shape    { };
    struct Rectangle_Type : public Shape { using value_type=int;         };
    struct Circle_Type    : public Shape { using value_type=std::string; };
    
    Rectangle_Type Rectangle;
    Circle_Type    Circle;
    
    static std::map<std::string,Shape*> g_mapping =
    {
        { "Rectangle", &Rectangle },
        { "Circle",    &Circle    }
    };
    
    int tag_dispatch( Rectangle_Type )
    {
        return 42;
    }
    
    std::string tag_dispatch( Circle_Type )
    {
        return "foo";
    }
    
    int
    main()
    {
        std::cerr << tag_dispatch( Circle    ) << std::endl;   // OK
        std::cerr << tag_dispatch( Rectangle ) << std::endl;   // OK
    
    #define BROKEN
    #ifdef BROKEN
        std::cerr << tag_dispatch( (*g_mapping["Rectangle"]) ) << std::endl;
        std::cerr << tag_dispatch( (*g_mapping["Circle"])    ) << std::endl;
    #endif
    }
    

2 个答案:

答案 0 :(得分:1)

除非C ++ 11改变了这个问题。问题是您正在取消引用Shape*指针,这意味着生成的数据类型(Shape&)没有{{1的有效重载}}。

您可以执行tag_dispatch之类的操作。或者更干净地重写如下。

g_mapping["Rectangle"]->tag_dispatch()

这样,您可以支持具有相同接口的非std::string tag_dispatch( Shape& shape) { return shape->tag_dispatch(); } 个对象。两者都需要您将Shape作为tag_dispatch的虚函数。

答案 1 :(得分:0)

C ++没有动态调度。这可能是您期望发生的事情。您可以使用dynamic_cast模拟它,但这很慢而且不推荐。您可以使用虚函数返回该类型的枚举。

class base
{
public:
    virtual ~base() // Don't forget the virtual destructor if you want to inherit from it!
    {}

    enum type
    {
        a, 
        b, 
    };

    virtual type get_type() const = 0;
};

class a : public base
{
public:
    virtual type get_type()
    {
        return base::type::a;
    }
};

class b : public base
{
public:
    virtual type get_type()
    {
        return base::type::b;
    }
};