如何从成员方法返回多种类型

时间:2018-12-07 06:57:22

标签: c++ c++11

我正在尝试编写一个类方法,该方法可以根据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 A str 成员变量(如何解决此问题)以及类如何相关方法返回不同的变量值?

$ 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);

                 ^

1 个答案:

答案 0 :(得分:0)

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

(在C ++ 17中,您可以使其看起来像从函数返回不同的类型,但这实际上是针对各种值实例化的模板)

如果您要根据所包含的并集类型选择要执行的操作,则可以改用std::variant的灵感,并接受带有多个operator()的函数对象,每种可能一个类型。

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<int32_t, uint32_t, uint64_t, bool, std::string>;