Solved

declaring vector type based on size in switch statement

Posted on 2014-01-12
5
367 Views
Last Modified: 2014-01-29
Hi

I would like to declare a vector but its type (whether char, float etc) needs to be determined based on the results of a switch statement.

switch(a){

     case 8:
     {
        std::vector<unsigned char> my_vector; break;
     }
     
    case 16:
    {

        std::vector<unsigned short> my_vector;break;
     }

     case  32:
     {

          std::vector<float> my_vector;break;
      }

    default:
    {
          std::vector<unsigned char> my_vector; break;
     }
}

my_vector.insert(my_vector.begin()+offset,myvalue);

but later down , after the switch statement ends,in the same function , when i try to perform an insert operation on my_vector, i get 'my_vector' :undeclared identifier.

what can i do to ensure that i have a my_vector that is created based on the results of the switch statement?
0
Comment
Question by:LuckyLucks
5 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 250 total points
ID: 39775612
You can't do that based on a 'switch' statement, but a template can well serve that purpose. E.g.

template<typename T>
T create_vector_and_add_value(const T myvalue, const size_t offset) {

  std::vector<T> my_vector;

  my_vector.insert(my_vector.begin()+offset,myvalue);

  return my_vector;
} 

Open in new window


Your above code won't work because the vectors you create are 'local' to the scope in between the scope braces ('{}') and therefore no longer valid later in your code. But apart from that, the approach is flawed - how would you return a type that you are not sure of what it is in the beginning?
0
 
LVL 16

Expert Comment

by:HooKooDooKu
ID: 39775613
Simply put, variables can not be declared within a switch statement EXCEPT for variables that will have a scope of a single case (and the case must have {} around it:
switch(i)
{
  case 0:
  {
    int j=0;
    //... do stuff with j
  } //j goes out of scope here
}

Open in new window


About the only way I can thing to accomplish what you want to do is to use a pointer or a union.  

If you use a union, then you could use the switch statement to decide which data type within the union to process within the switch statement.

My personal approach would be to define a class and declare a pointer to that class.  Then inside the switch statement, create a new instance of the class where you could pass a parameter to the constructor to determine which 'mode' to create the class.
class myvectors
{
public:
  enum mode
  {
    CharMode,
    ShortMode,
    FloatMode
  ]
  mode m_mode;
  (std::vector<char>)* m_pChar;
  (std::vector<short>)* m_pShort;
  (std::vector<float>)* m_pFloat;
  myvector(mode){
    m_mode = mode;
    m_pChar = NULL;
    m_pShort = NULL;
    m_pFloat = NULL;
    switch( m_mode )
    {
      case CharMode: m_pChar = new std::vector<char>; break;
      case ShortMode: m_pShort = new std::vector<short>; break;
      case FloatMode: m_pFloat = new std::vector<float>; break;
    {;
};

Open in new window

From there, you would directly work with the vector that currently has a value, or when the functionality is the same regardless of the vector used, create a member function that looks at mode and determines which member variable to operate on.

I'm sure there might be some additional options if you started getting into templates.  But again, even there you basically can not change the declaration of a variable within a switch statement.  (In other words, you can change how a variable expresses itself within a switch statement, but you can't change how it is declared)
0
 
LVL 24

Expert Comment

by:chaau
ID: 39775622
You can't do this. First of all when you define a variable inside the {...} block it is called that it is declared inside the scope of this block. So, the statement like this:
 {
        std::vector<unsigned char> my_vector; break;
 }

Open in new window

will only exist inside the {...} brackets. That is why you are getting these errors.
The my_vector variable has to be defined in the scope of the code you are going to use, in your case, in the beginning of the program.
To address your problem you have a few options:
1. Define my_vector as a type that is guaranteed to hold all possible values, e.g. double. Then just cast to the type you want inside your switch statement. However, please note that due to double's rounding problems you can experience some unexpected problems when casting the values to/from float.
2. Create a class that will use the type value and a union with different types. Then create the vector using this class. Here is a small example:
class Universal
{
public: 
  union val
  {
    float f;
    unsigned short us;
    unsigned char uc;
  } value;
  int type;
  Universal()
  SetType(int t){type = t;};
  SetFloat(float f)(value.f = f;);
  etc...
};

Open in new window

Now, you can define my_vector as  std::vector<Universal> my_vector;
3. You can define the vector as
 std::vector<void*> my_vector;
and populate the values like this:
 std::vector<void*> my_vector;
switch(a){
    case 16:
    {
        // b is a value you want to insert
        my_vector.push_back(new float(b));break;
     }

Open in new window

Please note that in this case you need to delete every element you are inserting using delete operator:
 while (!my_vector.empty())
  {
    delete my_vector.back();
    my_vector.pop_back();
  }

Open in new window

There are some other options, and I am pretty sure other experts give you their own answers....
0
 
LVL 40

Expert Comment

by:evilrix
ID: 39775830
Is the value of the variable 'a' known at compile time? If so this is easy to do with a little bit of template trait magic. If not, see above.
0
 
LVL 32

Assisted Solution

by:sarabande
sarabande earned 250 total points
ID: 39776862
what can i do to ensure that i have a my_vector that is created based on the results of the switch statement?

if using a void pointer you could do it like that:

enum { chartype, shorttype, floattype };

class VarVector
{
    void * pv;
    int  type;
public:
    VarVector(std::vector<unsigned char>* p) : pv(p), type(chartype) {}
    VarVector(std::vector<unsigned short>* p) : pv(p), type(shorttype) {}
    VarVector(std::vector<float>* p) : pv(p), type(floattype) {}

    void push_back(int off, unsigned char uc) 
    { 
         if (type == chartype) ((std::vector<unsigned char>*)p)->push_back(uc);
    }
};

...
VarVector * pvv = NULL;
switch(a)
{
    case 8:   pvv = new VarVector(new std::vector<unsigned char>()); break;
    case 16: pvv = new VarVector(new std::vector<unsigned short>()); break;
    ...
}

Open in new window


however, the code is not very convenient cause for the insert or push_back function you would need a further switch cause 'myvalue' also needs to be the right type. so the problem is not so much that you need a container that takes an arbitrary type but that you need a variant type. for that the union as shown by jkr is an often used concept, though it is a c-like design and I would not use it for c++.

a c++ variant type would look different:

enum { ebytetype, eu16type, efloattype };

class basevariant
{
public:
      int gettype() = 0;   // makes basevariant an abstract class
};     

class bytevariant : public basevariant
{
      unsigned char uc;
public:
       bytevariant(unsigned char c) : uc(c) {} 
      unsigned char getvalue() { return uc; }
       int gettype() { return ebytetype; }
};
....
class variant
{
     basevariant * pbv;
public:
     variant() : pbv(0) {}
     variant(unsigned char uc) : pbv(new bytevariant(uc)) {}
     // other constructors
     virtual ~variant() { delete pbv; }
};

....
std::vector<variant> vv;
...
switch (a)
{
   case 8: 
   {
         unsigned char uc = (unsigned char)atoi(mystrvalue.c_str());
         vv.insert(vv.begin()+off, uc);
         break;
   }
   ....

Open in new window


the above allows to store different base types to the same vector.

Sara
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now