如何处理为相同的输入数据类型返回不同数据类型的api?

Gre*_*reg 4 c++ types function c++11 c++14

如何处理为相同的输入数据类型返回不同数据类型的api?

查看下面的示例,apicall应该根据输入属性返回日期或字符串:

#include <iostream>
#include <string>

using namespace std;

???? apicall(string datatype, string attribute)
{
    // code
}

int main(int argc, char** argv)
{
    string datatype = "Thomas"
    string attribute = "bithday"
    cout << apicall(datatype, attribute) << endl;

    string datatype = "Thomas"
    string attribute = "address"
    cout << apicall(datatype, attribute) << endl;
}
Run Code Online (Sandbox Code Playgroud)

什么可以代替????(apicall返回数据类型)以及如何处理这些情况?

我试图理解这些概念,因为我迄今为止的经验是使用duck typed脚本语言.

Use*_*ess 6

...为相同的输入数据类型返回不同的数据类型?

这实际上是不可能的.函数定义为一个(或零)返回类型,以及零个或多个输入参数类型.

解决方法是:

  1. 编写一个返回变量类型的函数,例如C++ 17中的std :: variant,如果不可用,则返回Boost.Variant.
  2. 使用不同的返回类型编写多个函数(调用者只需选择正确的函数)
  3. 反转控制,以便传递一个能够处理所有必需类型的对象,而不是返回值:

    struct APIHandler {
      virtual ~APIHandler() {}
      virtual void operator()(int) {}
      virtual void operator()(string) {}
    };
    void apicall(string name, string attr, APIHandler &h) {
      // dummy implementation
      if (attr == "address") {
        h("123 Woodford Road");
      } else if (attr == "birthday") {
        h(19830214);
      }
    }
    
    // implement your type-specific logic here
    struct MyHandler: APIHandler {
      void operator()(int i) override {
        cout << "got an int:" << i << '\n';
      }
      void operator()(string s) override {
        cout << "got a string:" << s << '\n';
      }
    };
    
    // and use it like:
    MyHandler mh;
    apicall("Thomas", "birthday", mh);
    apicall("Thomas", "address", mh);
    
    Run Code Online (Sandbox Code Playgroud)


Bia*_*sta 6

理想的解决方案是使用a std::variant,这是一种安全的联合类型.

这允许您编写以下内容:

using DateOrString = std::variant<DateType, std::string>;

DateOrString api_call(std::string, std::string) {
   // you can return both DateType and std::string
}

// ...
auto result = api_call("", "");
auto& str = std::get<std::string>(result);
Run Code Online (Sandbox Code Playgroud)

不幸的std::variantC++ 17的功能.然而,不同的编译器已经支持它.

正如已经建议的那样,boost有一个variant类,您可以将它与任何C++标准一起使用.


作为最后一个选项,您可以实现一个"类似变体"的类来处理日期和字符串.你的函数应该返回它.

这里有一个演示如何快速实现那​​种类.

请注意,该类是安全的,因为在运行时检查了类型.

作为变体对象,您的被调用函数应该在类型上分支,例如:

auto result = api_call(/*...*/);
if (result.is_string()) {
   // result is a string
   const auto& str = result.get_string();
} else {
   // result is a date
   const auto& date = result.get_date();
}
Run Code Online (Sandbox Code Playgroud)