Why can't redefine type names in class in C++?

why can't
why can't i meaning
why can't i liz phair movie
why can't i 13 going on 30
why can't we be friends
liz phair - extraordinary
liz phair - supernova
why can't i share a post to a group on facebook

According to the book C++ Primer section, 7.4.1 Type Names Are Special:

Ordinarily, an inner scope can redefine a name from an outer scope even if that name has already been used in the inner scope. However, in a class, if a member uses a name from an outer scope and that name is a type, then the class may not subsequently redefine that name.

Accordingly, for example:

typedef double Money;
class Account {
    public:
        Money balance() { return bal; }
    private:
        typedef double Money;
        Money bal;
};

int main() {
    typedef double Money;
    Money asset;
    typedef double Money;
    return 0;
}

When you compile the example above, it will complain:

a.cc:6:24: error: declaration of ‘typedef double Account::Money’ [-fpermissive]
         typedef double Money;
                        ^
a.cc:1:16: error: changes meaning of ‘Money’ from ‘typedef double Money’ [-fpermissive]
 typedef double Money;

So why can not we redefine type names in class, but can we in the inner scope?


My compiler version is g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609. And there is also a note in that section:

Although it is an error to redefine a type name, compilers are not required to diagnose this error. Some compilers will quietly accept such code, even though the program is in error.

This is not unique to types. [basic.class.scope]/2:

A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.

The reason is that name lookup in class scope is a little special. Consider:

using Foo = int;

struct X {
    Foo a;    // ::Foo, i.e., int
    void meow() { 
        Foo b = a; // X::Foo; error: no conversion from int to char*
    }
    using Foo = char*;
};

Name lookup in member function bodies considers all class members, whether declared before or after the member function (otherwise, a member function defined in a class definition wouldn't be able to use a data member declared later in the class). The result is that you get two Foos with different meanings, even though they both lexically precede the class member Foo's declaration. This can easily lead to extremely confusing and brittle code, and so the standard bans it.

Liz Phair - Why Can't I? (Official Video), We understand that this can be frustrating, so please keep in mind that you'll receive a notification at the top of the group indicating when you'll be able to post​  When you get a message that says Windows can't be activated, there are several possible reasons why. Select any of the following topics to see some typical reasons for activation difficulty, along with possible ways to get going again.

When the compiler reads the line

    Money balance() { return bal; }

in the class definition, it already uses the definition of Money outside the class. That makes the line

    typedef double Money;

inside the class a problem. However, you may use redefine Money inside the class before it is used in the class. The following is OK.

typedef double Money;

class Account {
    public:
        typedef double Money;
        Money balance() { return bal; }
    private:
        Money bal;
};

The key point in the quote is:

hence the class may not subsequently redefine that name.

Why can't I post in a Facebook group?, Facebook is a community where people use the name they go by in everyday life. And I can't recall any love at all Oh baby, this blows 'em all away It's got what it takes So tell me why can't this be love? Straight from my heart Oh tell me why Can't this be love? I tell

I would like to try to answer some questions from your comments.

Comment 1

"But in the function main, we can redefine typedef double Money even if it is defined after the statement Money asset"

So you are asking, why typedef identifier can be defined more than once in a non-member function(in a non-class scope)?

The answer is here:Repeated typedefs - invalid in C but valid in C++?

Comment 2

So, in this example, two Foos with different meaning both lexically precede the statement Foo b = a in function meow. Then the compiler can't determine which the type of b is. Is it correct or not?

The complier can determine the type of b in that code chunk. B's type is obvisouly char* while the type of a is int.

Although two Foo with different meaning both lexically precede the statement Foo b = a in function meow, Foo defined as int precedes Foo defined as char*. The book says that the name lookup process is different:

• First, the member declarations are compiled. • Function bodies are compiled only after the entire class has been seen.

So in the first step, while compiling member declarations, Foo a and using Foo = char* get compiled in order. And the first Foo uses outside definition of Foo, which is int. Then, an inner scope Foo is created, with type char*. After that, the compiler starts to compile the function body. For function meow, Foo b uses inner scope Foo, which is char*, while for a, which is already get compiled in the first step, is a int Foo. So that's how the conversion error occurs.

Comment 3

I want to know is that why "the class may not subsequently redefine that name." But "an inner scope can redefine a name from an outer scope even if that name has already been used in the inner scope." –

R Sahu's point (and I think it is what the book wants to say) is that if you really want to redefine a typedef identifier, you can only do this in the very beginning of your class. So there won't be any "ambiguity" about that identifier among the context.

Summary:

Allow this:

(This can't compile in g++ (because standard ban this) but can in Visual Studio, because logically there's no conflict here.)

typedef double Money;
class Account {
    public:
        Money balance() { return bal; }
    private:
        typedef double Money;
        Money bal;
};

is very easy to cause things like this:

(can't compile in both g++ and Visual Studio, because logically there is conflict here.)

using Foo = int;

struct X {
    Foo a;    // ::Foo, i.e., int
    void meow() { 
        Foo b = a; // X::Foo; error: no conversion from int to char*
    }
    using Foo = char*;
};

so if you really want to redefine a typedef identifier inside a class. Only do this:

(can compile in both g++ and Visual Studio, because logically there's no conflict here and standard only allows this.)

typedef double Money;

class Account {
    public:
        typedef double Money;  
        //put the redefine statement in the very beginning
        Money balance() { return bal; }
    private:
        Money bal;
};

PS:

Explain the code:

typedef double Money;
class Account {
    public:
        Money balance() { return bal; }
    private:
        typedef double Money;
        Money bal;
};

These code is logically right but for standard it is banned. Same compiling step as mentioned above, first compile function balance's declaration, so Money here is the outside Money. Then complie typedef double Money we get a inner scope Money and the type of bal is Account::Money not the outside one.

So practically you can do this with Visual Studio compiler but not with g++:

typedef double Money;
class Account {
    public:
        Money shit = 12.34; //outside money, type is double
    private:
        typedef string Money;  
        Money bal;   //bal is string not double
};

Thanks for the enlightenment from the other two answers. And there's some prediction in my post which is my personal deduction. If there's anything wrong, feel free to correct it.

Why can't I change my name on Facebook?, If you're having trouble logging in, you may be entering incorrect account information or you may need to reset your password. Here are some things to check:. Why Can't I Get or Keep an Erection? In this Article In this Article In this Article. Is the Problem All in My Head? Can I Blame My Medicines? Could My Lifestyle Play a Role? How About My Age?

Amazon.com Help: Why Can't I Log into My Account?, There are privacy settings and legal requirements that may restrict access to certain features on Duolingo. You may have enabled Cannot definition is - can not. How to use cannot in a sentence.

Why can't I access certain features, such as Flirting skill, forums or , Its ok – we got this. First you have to create an account and password on Afterpay to log in. You can do this after your first purchase Can’t go? You’re not alone. About 20% of Americans have occasional constipation-- bowel movements less than three times a week.Or if they do poop, the output is hard, small, and painful to

Why can't I log in to Afterpay? – Afterpay, That is why we must reform our election systems, so that sheltering in place can also mean voting in place. And we must do it now, while we still  There could be several reasons why you aren't receiving your e-mail messages. Please review the following situations to see if one applies to you: Did you just move your domain name to Network Solutions® or register a new domain name? If so, it will take approximately 12-36 hours for the domain name information to propagate to servers worldwide.

Comments
  • What if you changed the order of the lines in main to have the typedef after the Money asset?
  • @Justin, it is ok in main function though changing the order of the lines.
  • That can make for some interesting error messages: wandbox.org/permlink/N918N1IqbP2E5g0O . I guess it's just not prohibited for inside functions, but it is for inside classes
  • @Justin, my compiler is g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609.
  • Classes are kind of funny. You know how you can use a member variable that hasn't been defined yet in a method? If you have a disconnect in types between that member variable and the method, that's gotta be a real head-trip for the poor compiler.
  • So, in this example, two Foos with different meaning both lexically precede the statement Foo b = a in function meow. Then the compiler can't determine which the type of b is. Is it correct or not?
  • This answer is a great example.
  • But in the function main, we can redefine typedef double Money even if it is defined after the statement Money asset.
  • I want to know is that why "the class may not subsequently redefine that name." But "an inner scope can redefine a name from an outer scope even if that name has already been used in the inner scope."