有没有创建包含对不同类型变量的引用的数组/向量的方法?

时间:2016-10-18 13:25:36

标签: c++ arrays vector reference

我现在已经敲了很长时间试图创建一个可以包含对几种类型变量的引用的数组/向量,请参阅示例:

class Validate
{
private:
   some_array/vector[]; //0 would refer to x, 1 to y, and so on..
   uint8_t x;
   uint16_t y;
   int32_t z;
public:
   Validate();
   void doSomething(uint8_t &member);
   void doSomething(uint16_t &member);
   void doSomething(int32_t &member);
}

重点是我可以在" for循环"中轻松使用这个数组/向量,如下所示:

void Validate::doSomething(uint_8 &member)
{
   //Do whatever with the variable refered to.
}
Validate::Validate()
{
   for(int i = 0 ; i < 2 ; i++)
      doSomething(some_array/vector[i]);
}

也许有人对我有答案或可能是更好的解决方案。

1 个答案:

答案 0 :(得分:0)

你有两个问题。首先,容器不能包含不同类型的元素。其次,您不能将引用存储在容器中。

解决第一个问题的一种方法是使用C ++ 17(或std::variant)中的boost::variant。要解决第二个问题,您可以使用std::reference_wrapper

class Validate {
   using Uint8Ref   = std::reference_wrapper<uint8_t>;
   using Uint16Ref  = std::reference_wrapper<uint16_t>;
   using Uint32Ref  = std::reference_wrapper<int32_t>;
   using MemberType = std::variant<Uint8Ref, Uint16Ref, Uint32Ref>;

   std::vector<MemberType> members;
   uint8_t                 x;
   uint16_t                y;
   int32_t                 z;

public:
   Validate();
   void doSomething(uint8_t &member);
   void doSomething(uint16_t &member);
   void doSomething(int32_t &member);
};

Validate::Validate() : members({std::ref(x), std::ref(y), std::ref(z)}) {    
   for (auto member : members) {
      std::visit([this](auto member){this->doSomething(member);}, member);
   }
}

Live demo

或者,您可以为可以存储在容器中的成员创建多态基类:

class MemberType {
public:
 virtual ~MemberType(){}
 virtual void accept(Validate& validate) = 0;
};

class Validate {    
   std::array<std::unique_ptr<MemberType>, 3> members;
   // as before...
};

template<typename T>
class MemberTypeImpl : public MemberType {
  T& member;
public:  
  MemberTypeImpl(T& member) : member(member){}
  void accept(Validate& validate) override {
    validate.doSomething(member);
  }
};

template<typename T>
std::unique_ptr<MemberType> make_member_type(T& member) {
  return std::make_unique<MemberTypeImpl<T>>(member);
}

Validate::Validate() 
  : members({make_member_type(x), make_member_type(y), make_member_type(z)}) {
   for (auto& member : members) {
      member->accept(*this);
   }
}