3

When I try to compile this code:

#include <iostream>

namespace Direction
{
    enum Enum { UP, DOWN, LEFT, RIGHT };
}

using namespace std;

void move(int pDir);

int main()
{
    printf("UP: %u\n", Direction::UP);
    printf("DOWN: %u\n", Direction::DOWN);
    printf("LEFT: %u\n", Direction::LEFT);
    printf("RIGHT: %u\n", Direction::RIGHT);

    move(Direction::UP);

    return 0;
}

void move(int pDir)
{
    printf("Move: ");
    switch(pDir) 
    {
        case(Direction::UP):
            printf("UP");
            break;
        case(Direction::DOWN):
            printf("DOWN");
            break;
        case(Direction::RIGHT):
            printf("RIGHT");
            break;
        case(Direction::LEFT):
            printf("LEFT");
            break;
        default:
            printf("nothing");
            break;
    }
}

The result I expect would be:

UP: 0
DOWN: 1
LEFT: 2
RIGHT: 3
Move: UP

Instead the result is:

UP: 0
DOWN: 1
LEFT: 2
RIGHT: 3

It seems like void move(..) just gets ignored.

I already found the problem: It's the using namespace std. When I delete it, I get the result as expected.

So I have three questions:

1) Why does void move(..) just gets "ignored"

2) Why can I access the members of Direction within the first four lines of int main()

3) How can I fix this? ,_,

Have a nice day my friends.

ps: This is an extracted example of my problem, on my project I need to use the namespace std.

11
  • 3
    not sure if thats the problem here, but at least it is a source of confusion: dont use using namespace std;, there is also std::move, do you know which one it is when you write move ? ;) Commented May 15, 2018 at 9:02
  • 2
    just saw the "I need to use the namespace std" but tbh i cannot believe it. why do you need to do such a terrible thing? Commented May 15, 2018 at 9:03
  • 1
    @user463035818 That's the exact problem. (Well, plus the UB with the printfs) Commented May 15, 2018 at 9:04
  • 1
    its a matter of taste, but i would not even do that, once you are using std::move you again cannot easily spot the difference between std::move or ::move (btw ::move might fix your problem, but I am not sure at all) Commented May 15, 2018 at 9:09
  • 2
    Or you can just type std::cout. explicit > implicit. Those few characters aren't that hard to type. Eventually, if in a specific scope you use an identifier from ::std a lot, you should using std::identifier to save some typing. But in general, just be explicit and help your future self ;) Commented May 15, 2018 at 9:09

2 Answers 2

2

Your move function application has been reviewed and unfortunately, a better application has been found. Please don't hesitate to reach us for comments or questions.

std::move in utility header is the function being called in this situation. This is due to multiple factors :

  • The utility header is included by iostream, so it is defined in your code
  • Because of using namespace std, any function definition in the std namespace is now candidate for overload resolution in the global scope (see Namespace scope).
  • The argument Direction::UP is a rvalue, and the signature of std::move is template< class T >constexpr typename std::remove_reference<T>::type&& move( T&& t ) noexcept;. T can resolve to the enum type without conversion.
  • Yours is void move(int pDir); and will require an implicit conversion from Direction::Enum&& to int

When you remove on of these condition your function will be called. For instance

move((int)Direction::UP);

remove the need for an implicit conversion.

Sign up to request clarification or add additional context in comments.

Comments

2

Due to your using namespace std both move (yours) and std::move are now accessible through the name move and when you call it, the usual overload resolution takes place, so the compiler checks whether

move(int)

or

template<typename T> move(T) // bit simplified here

is a better match for your call move(Direction::UP). Since the underlying type (aka std::underlying_type) of an unscoped enum is implementation defined, it may be a char or short (or anything else), in which case the second candidate is a better match.

Other factors (like the rvalue-ness mentioned by UmNyobe) and the namespace of the arguments can as well have an influence on overload resolution. Moving the definition of your move into the Direction namespace for example should lead to the first candidate being called, since ADL (argument dependent lookup) kicks in, although I am not 100% sure on that right now.

So my advice, as already suggested by the others, is to avoid using namespace as much as possible, at least at file scope. If you need to access a lot of stuff from one namespace, simply put the using namespace into the function that requires it. Regarding namespace std in particular, I highly recommend to never use using namespace std.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.