【问题标题】:How to return multiple types from a member method如何从成员方法返回多种类型
【发布时间】:2018-12-07 20:18:04
【问题描述】:

我正在尝试编写一个类方法,该方法可以根据 DataType 结构变量中保存的值返回任何一个成员变量值。我试过下面的代码:

#include <iostream>
struct A
{
    int DataType;/* holds enum value for one of below data data needs to be returned  */
    union /* value of var is one of these needs to be returned */
    {
       int32_t x;
       uint32_t y;
       uint64_t mz;
       bool    b;
       struct         
       {
          char* ptr;
          int len;    
       } str;              
    }data;
};


struct A a1 = { /* value 1 means int32_t, 2 means uint32_t, 3 means uint64_t , 4 means bool and 5 means str */ 2, 32};
//struct A a2 = { /* value 1 means int32_t, 2 means uint32_t, 3 means uint64_t , 4 means bool and 5 means str */ 5, {{ "Hello",5}}};
class B
{
public:
   B(){}

   template <>
   T GetVar(struct A a0)
   {
      if (a0.DataType == 2)
         return a0.data.y;
      if (a0.DataType == 5)
         return std::string(a0.data.str.ptr);
      return 0;
   }
};

int main()
{
  B b1;
  auto d = b1.GetVar(a1);
  std::cout << d << std::endl;
  //auto d1 = b1.GetVar(a2);
  std::cout << d << std::endl;
}

我得到编译错误 - 我知道错误与初始化 struct Astr 成员变量有关(如何解决这个问题)以及类如何方法返回不同的变量值?

$ c++ -std=c++11 try72.cpp
try72.cpp:26:11: error: explicit specialization in non-namespace scope 'class B'
 template <>
           ^
try72.cpp:27:1: error: 'T' does not name a type
 T GetVar(struct A a0)
 ^
try72.cpp: In function 'int main()':
try72.cpp:40:13: error: 'class B' has no member named 'GetVar'
 auto d = b1.GetVar(a1);
             ^
try72.cpp:42:14: error: 'class B' has no member named 'GetVar'
 auto d1 = b1.GetVar(a2);
              ^
try72.cpp:42:21: error: 'a2' was not declared in this scope
 auto d1 = b1.GetVar(a2);

                 ^

【问题讨论】:

  • 编译器是正确的,你永远不会在任何地方声明T。无论如何,您不能从单个函数返回不同的类型。您可能想查看std::variantstd::any。或者甚至可以使用union 作为返回值?
  • @Programmer:您可以查看我为类似问题编写的答案。 stackoverflow.com/questions/53590671/….
  • @P.W - 谢谢,但 std::variant 在 C++ 17 中,我正在使用 C++11 - 有没有办法实现目标?
  • 那么您唯一的解决方案是 Boost 库(boost::variantboost::any)或联合。
  • @Programmer:我同意 SomeProgrammerDude 的建议。

标签: c++ c++11


【解决方案1】:

一个函数有一个返回类型。您需要不同的函数来返回不同类型的值。

(在 C++17 中,您可以让它看起来像是从函数返回不同的类型,但它实际上是一个模板,针对不同的值进行了不同的实例化)

如果您想根据联合的包含类型选择要执行的操作,您可以改为从std::variant 中获取灵感,并接受具有多个operator()s 的函数对象,每个可能的类型一个。

template <typename Return>
struct AVisitor
{
    virtual Return operator()(int32_t) const = 0;
    virtual Return operator()(uint32_t) const = 0;
    virtual Return operator()(uint64_t) const = 0;
    virtual Return operator()(bool) const = 0;
    virtual Return operator()(std::string) const = 0;
};

template <typename Return>
Return visit(const A & a, const AVisitor<Return> & visitor)
{
    switch (a.DataType)
    {
         case 1: return visitor(a.data.x);
         case 2: return visitor(a.data.y);
         case 3: return visitor(a.data.mz);
         case 4: return visitor(a.data.b);
         case 5: return visitor(std::string(a.data.str.ptr));
    }
}

struct cout_visitor : AVisitor<void>
{
    void operator()(int32_t x) const { std::cout << x; }
    void operator()(uint32_t y) const { std::cout << y; }
    void operator()(uint64_t mz) const { std::cout << mz; }
    void operator()(bool b) const { std::cout << b; }
    void operator()(std::string str) const { std::cout << str; }
}

int main()
{
    cout_visitor vis;
    visit(a1, vis);
    visit(a2, vis);
}

虽然显而易见的替代方法是将A 定义为using A =std::boost::variant&lt;int32_t, uint32_t, uint64_t, bool, std::string&gt;;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    • 2016-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多