【问题标题】:How do I get tag dispatch to work with strings?如何让标签调度与字符串一起使用?
【发布时间】:2013-01-30 02:33:54
【问题描述】:

我需要帮助才能让这段代码的损坏部分正常工作。

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

如果可以简化整体代码以使用字符串进行调度,请提出建议。泰。

要求:

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

代码

#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
}

【问题讨论】:

  • @Non-StopTimeTravel 实现不佳(当意图是使用字符串进行调度时),需要一些其他满足要求的技术
  • 实施不善如何?我试图让你提出一个实际的具体问题陈述。
  • @Non-StopTimeTravel OP 已修复

标签: c++ templates c++11


【解决方案1】:

除非 C++11 对此进行了更改。问题是您正在取消引用 Shape* 指针,这意味着生成的数据类型 (Shape&amp;) 没有 tag_dispatch 的有效重载。

您可以执行g_mapping["Rectangle"]-&gt;tag_dispatch() 之类的操作。或者更干净地重写如下。

std::string tag_dispatch( Shape& shape)
{
    return shape->tag_dispatch();
}

这样您就可以支持具有相同接口的非Shape 对象。两者都需要您将tag_dispatch 设为Shape 的虚函数。

【讨论】:

  • 是的,我意识到这就是问题所在 - 我可以使用其他一些技术来有效地基于字符串标记调度吗?
  • @kfmfe04 g_mapping["Rectangle"]-&gt;tag_dispatch() 如果您将其添加为虚拟函数,它将起作用。
  • 快到了!如果我使用虚函数,如何处理变体返回值(Rectangle 的版本返回一个 int,但 Circle 的返回一个字符串)?也许以某种方式使用模板?
  • @kfmfe04 “42”?我想不出一个巧妙的方法来做到这一点..你也可以用Rectangle_Type&amp;写另一个重载..
  • @kfmfe04 tag dispatching 似乎是一种纯粹的编译时技术。需要这样用吗?
【解决方案2】:

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;
    }
};

【讨论】:

  • 我在考虑使用 virtuals,但我的要求之一是让 Rectangles 返回一个 int 而 Circle 返回一个字符串。不确定如何在虚拟环境中适应它。
  • 我相信virtual functions do implement dynamic dispatch。你想说的是C++没有动态dispatch ON方法参数。
  • @kfmfe04 这在 C++ 中不会那么容易工作。问题再次是它没有动态调度。 (输出函数重载也需要动态确定类型。)所以,正如我所说,我看到的唯一方法是使用一个返回类型枚举的虚函数,而不是实现所有调度自己。
  • @cooky451 你能简单地画一个代码 sn-p 来告诉我如何做到这一点吗?泰。
  • @kfmfe04 我编辑了我的答案。您现在可以在 get_type 上使用 base& 或 base* 和 switch ()。但是请注意,如果您有动物和老虎。因此,这种方法有些局限性,但它可能对您来说效果很好。
猜你喜欢
  • 1970-01-01
  • 2023-02-24
  • 1970-01-01
  • 1970-01-01
  • 2022-01-18
  • 2016-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多