1

I have to write a simple code that takes a char as input or a string with an integer. Then makes a std vector, depending on the input. If the text says int I have an int vector. The only problem is that I don't want to declare for each variable type a vector even if empty, and I want to make it scalable so if someday I want to put a struct or something else in it i can.

dvec::dvec( char t){
if ( t=='i')
    vector<int> a;
else if( t=='f')
    vector<float> a;
}
1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
Hack Er
  • 11
  • 2
  • 2
    why not use a template? – yaodav Jun 03 '20 at 18:22
  • 3
    @yaodav You'll still have trouble using your object, its type depends on runtime information. You'll need to use a `variant`, template everything that uses it or use another scheme to abstract away the concrete type. – François Andrieux Jun 03 '20 at 18:27
  • We probably have to know the context on how this class is expected to be used. if the information about type is only known at runtime or is it known at compile time. The `char t` parameter suggests runtime but I am not sure that is needed. – drescherjm Jun 03 '20 at 18:29
  • 1
    *i have to write a simple code..." I don't think you can have a simple code for this. – user4581301 Jun 03 '20 at 18:31
  • you can also use (if you're using c++17) [std::any](https://en.cppreference.com/w/cpp/utility/any) or [std::variant](https://en.cppreference.com/w/cpp/utility/variant), but when you trying to use the variable you need to know the type – yaodav Jun 03 '20 at 18:40
  • How about using `std::any`? – Amal K Jun 03 '20 at 18:41

3 Answers3

0

If all you want is primitive types or pointers, you can make a union (8 bytes in size) and a vector of that union. It's a bit C'ish, but template is a compile time solution, so for a linkable solution, you need space for every type. You can have getters, setters, constructors for each type.

0

You can implement this thing in two ways:

1.

using element_type = std::variant<char, int, float /* ... other types */>;

using dvec = std::vector<element_type>;

This will be type safe, albeit the disadvantage is that every element of the vector is a variant, which might not be what you want.

2.

using dvec = std::variant<std::vector<char>,
                          std::vector<int>,
                          std::vector<float> /* ... other vector types */>;

This will give you a variant of vectors, where all vector elements are homogeneous.

This cumbersome expression could be simplified by using Boost.Mp11

    template<class T> using vectorize_t = std::vector<T>;

template<typename ...T>
    using dvec = std::variant<mp_transform<vectorize_t, T...>>;

which basically puts all respective types in T... to an std::vector.

jvd
  • 764
  • 4
  • 14
0

Write a helper function to do the real work.

template <typename T>
void do_work() {
    std::vector<T> a;
    // do stuff
}
// ...
if(t == 'i') {
    do_work<int>();
}
else if(t == 'f') {
    do_work<float>();
}
else if(t == 's') {
    do_work<your_struct>();
}

Depending on what your specific uses are you might need (or at least want) to have do_work just call multiple functions, that way you can specialize if needed.

Stephen Newell
  • 7,330
  • 1
  • 24
  • 28