Aleph0
Aleph0

Reputation: 6084

Compiler Warning 4456 using VS 2015

If I compile the following small programm with Visual Studio 2015, I get the following compiler warning in line 9:

warning C4456: Declaration of "iter" shadows previous declaration

This is my small program:

#include <iostream>
#include <boost/variant.hpp>

int main(int argc, char** args) {
    boost::variant<double, int> v{ 3.2 };
    if (auto iter = boost::get<int>(&v)) {
        std::cout << *iter << std::endl;
    }
    else if( auto iter = boost::get<double>(&v)) {
        std::cout << *iter << std::endl;
    }
}

I'm curious if this is a compiler bug or a serious error.

Revised

As @Zeta found out, the following is legal C++ code, even I never imagined. The program will crash, due to using an undefined iter.

#include <iostream>
#include <boost/variant.hpp>

int main(int, char**) {
    boost::variant<double, int> v{ 3.2 };
    if (auto iter = boost::get<int>(&v)) {
        std::cout << *iter << std::endl;
    }
    else if( auto iter2 = boost::get<double>(&v)) {
        std::cout << *iter2 << std::endl;
        std::cout << *iter << std::endl;
    }
    return 0;
}

Upvotes: 0

Views: 1129

Answers (1)

Zeta
Zeta

Reputation: 105935

VS is correct. You have two iter at hand:

#include <iostream>
#include <boost/variant.hpp>

int main(int argc, char** args) {
    boost::variant<double, int> v{ 3.2 };
    if (auto iter = boost::get<int>(&v)) {
        std::cout << *iter << std::endl;
    }
    else if( auto iter2 = boost::get<double>(&v)) {
        std::cout << *iter << std::endl; // whoops
    }
}

That's because

if(value = foo()) { 
    bar();
} else { 
    quux();
}

is the same as

{
    value = foo();

    if(value) { 
        bar();
    } else { 
        quux();
    }
}

Note that value is in scope for else. This includes any nested if within the (implicit) else block. You can look this up in C++11's [stmt.select] section, paragraph 3:

… A name introduced by a declaration in a condition (either introduced by the type-specifier-seq or the declarator of the condition) is in scope from its point of declaration until the end of the substatements controlled by the condition. If the name is re-declared in the outermost block of a substatement controlled by the condition, the declaration that re-declares the name is ill-formed. [ Example:

if (int x = f()) {
    int x; // ill-formed, redeclaration of x
}
else {
    int x; // ill-formed, redeclaration of x
}

Upvotes: 2

Related Questions