Как вернуть несколько типов из метода-члена - PullRequest
0 голосов
/ 07 декабря 2018

Я пытаюсь написать метод класса, который может возвращать любое значение переменной одного члена на основе значения, хранящегося в структурной переменной 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;
}

Я получаю ошибку компиляции - и я знаю, что ошибка связана с инициализацией str переменной-члена struct A (какчтобы решить эту проблему), а также как метод класса может возвращать различные значения переменных?

$ 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 голосов
/ 07 декабря 2018

Функция имеет один тип возврата.Вам нужны разные функции для возврата значений разных типов.

(в 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>;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...