Question

I have a program that needs to set the type of a vector as the program is executed (according to a value in a configuration file).

I have tried this:

int a = 1

if(a == 1)  vector<int> test(6);
else  vector<unsigned int> test(6);

test.push_back(3);

But this gives me:

Error   1   error C2065: 'test' : undeclared identifier

I'm not entirely sure why, but I think this is because the vector is not actually decided at compile time so the compiler cannot work with it whilst compiling the rest of the code.

Is there a way to decide the type of a vector at runtime similar to what I have attempted above? I have tried to create one version outside the if and then delete it and re-write the new version inside the IF. This however feels wrong and I can't get it to work anyway. thanks.

Was it helpful?

Solution

The reason it does not work is that you're declaring the vectors inside the if- and else-block respectively, so they go out of scope once that block ends.

Is there a way to decide the type of a vector at runtime similar to what I have attempted above?

No, the type of a variable must be known at compile-time. Your only option is to put the line test.push_back(3) as well as any following code which accesses test into the if- and the else-block, or to avoid code-duplication into a second templated function. This could look like this:

template <class T>
do_something_with_test(vector<T>& test) {
    test.push_back(3);
    // work with test
}

void foo() {
    int a = 1

    if(a == 1) {
        vector<int> test(6);
        do_something_with_test(test);
    }
    else {
        vector<unsigned int> test(6);
        do_something_with_test(test);
    }
}

OTHER TIPS

The exact reason for the error you are getting is kind of a subtle one for a beginner, and it involves the scope of the variable test that you are creating. Simply put, you are creating the vector inside of the if statement, but by the time you are going to use it, it no longer exists because it has gone out of scope.

I have reformatted your code with brackets to make this effect more noticable. Note that my version is semantically equivalent to yours and will give the same error.

if(a == 1)
{
  vector<int> test(6);
}
else
{
  vector<unsigned int> test(6);
}

test.push_back(3);

That said, what you are trying to do seems a little weird, and I have to wonder what your end goal is. That is not to say that there are not ways to do what you seem to want to do, but I would need to know what your success criteria before I could suggest a more appropriate method.

I'm not sure why do you need that but I suggest you to try to use a vector of union to solve your problem, something like this

union DataType
{
    int intVal;
    unsigned uintVal;
}
std::vector<DataType> vec;

Or probably more elegant way is to use boost::variant instead of the union. Maybe if you give us more details about your problem you get a much better asnwer.

Good luck!

You could have a look at boost::any to achieve something similar.

Setting a vector's type (aka template instantiation) always happens at compile time. For more clarification check out the Wikipedia article on Template metaprogramming.

if you truly need a polymorphic Type, perhaps you could take a look at the boost::variant class or something similar;
This is designed to mimic some of the behavior of dynamic languages within C++, and is usually used for interfacing with (or implementing) them. you could create a "vector< Variant > a", and a.push_back(Variant((unsigned int)..). the constructors for values pushed need compile time type.

It would also be possible to make a vectorized variant class which stores the type information for the entire collection if you expected the values to be homogenous.

but, it's far more likely you can acheive the desired end result without such a mechanism, reworking your program to avoid runtime type checks perhaps (which would most likely negate some of the benefits of using C++ over another language in the first place).

You could write the type dependent parts as templates (as suggested above) and select an alternative code path based on the configuration file setting checked & dispatched once. This style of coding gets slightly easier in c++0x with 'auto' and decltype() too.

The specific case of unsigned versus signed values involves allowing one more bit which sounds unusual, or of marginal benefit compared to the added complexity, but I can easily imagine one wanting an implementation that can switch between single and double precision float for example.

Yet another simple option would be to make a compile time setting for the type (e.g. introduced as a define from the build settings or makefile), then distribute multiple versions of your program, which might make sense in some circumstances. However, the templates already suggested are more likely to be the most useful option.

In your example, you have independent instances of a variable test created in each branch of your if statement, each of which goes out of scope immediately. So when the compiler gets to test.push_back(3); there is no test variable in scope, hence the error.

To address your problem, you can't fight the type system: assuming that int and unsigned int are the actual types in question you'd be much better off using vector<int> throughout, presuming that you don't actually need the full range of an unsigned int.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top