Why A Big Difference between C++98 and C++0x on a local type as atemplate-argument?

Discussion in 'C++' started by xmllmx, Feb 6, 2010.

  1. xmllmx

    xmllmx Guest

    Dear all,

    C++98 14.3.1 explicitly says as follows:

    "A local type, a type with no linkage, an unnamed type or a type
    compunded from any of these types shall not be used as a template-
    argument for a template type-parameter."

    And the Standard also immediately gives an example:

    /*-- Source Code Begin --*/

    template <class T> class X {};

    void f()
    {
    struct S {};

    X<S> x3; // error: local type used as template-argument
    }

    /*-- Source Code End --*/

    Nevertheless, the source code should can be correctly compiled by
    Visual C++. Moreover, C++0x 14.4.1 explicitly says differently as
    follows:

    "A template-argument for a template-parameter which is a type shall be
    a type-id."

    C++0x 14.4.1 also immediately gives some examples as follows:

    /*-- Source Code Begin --*/

    template <class T> class X {};
    template <class T> void f(T t) {}
    struct {} unnamed_obj;

    void f()
    {
    struct A {};
    enum { e1 };
    typedef struct { } B;
    B b;
    X<A> x1; // OK
    X<A*> x2; // OK
    X<B> x3; // OK
    f(e1); // OK
    f(unnamed_obj); // OK
    f(b); // OK
    }

    /*-- Source Code End --*/

    Obviously, both of the most popular C++ compiler and C++0x relax the
    restrictions put by C++98.

    In my view, the new rules without restrictions are intuitive, easy to
    use for programmers and easy to implement for compilers. What makes me
    most puzzled is the hidden reason for the authors of C++98 to put such
    counterintuitive restrictions on compilers and on us innocent
    programmers? What's the WHY behind the C++98 restrictions?

    To my experience during learning C++, C++ always trys not to put any
    restrictions on programmers as much as possible except and ONLY except
    the following two cases:

    Case 1) One language feature/usage is dangerous and/or easy to misuse
    so that some specific restrictions are necessary. e.g. restrictions on
    const member functions.

    case 2) One language feature/usage can not be implementd by the C++
    compilers. e.g. restrictions on static_cast(staic_cast a pointer to a
    virtual base to another pointer to its derived class which have at
    least two immediate base classes. i.e the notorious diamond
    inheritence.)

    As the supreme authority in C++ world, I always regard C++98 as a
    bible-like masterpiece. I don't believe the authors of C++98 had not
    deeply thought the above-mentioned issue over and over before they
    decided to put such restrictions into the standard. However, I indeed
    could not get a convincing explanation only by myself. So I eagerly
    hope someone can give me that. Any help will be highly appreciated,
    many thanks in advance!
     
    xmllmx, Feb 6, 2010
    #1
    1. Advertising

  2. xmllmx

    Robert Fendt Guest

    Re: Why A Big Difference between C++98 and C++0x on a local type asa template-argument?

    And thus spake xmllmx <>
    Sat, 6 Feb 2010 04:13:32 -0800 (PST):

    > Obviously, both of the most popular C++ compiler and C++0x relax the
    > restrictions put by C++98.


    To call VC++ the "most popular C++ compiler" is actually quite a
    bold statement. That holds true only if your entire world
    consists of Win32 desktop applications. Other compilers like
    Comeau, Intel and GCC exist not without reason. Especially GCC,
    which supports nearly any platform on the *planet*. If you look
    at other domains like embedded systems, POSIX, scientific
    computing etc. you will find that your "most popular" compiler
    is more or less useless in every single one of them.

    > In my view, the new rules without restrictions are intuitive, easy to
    > use for programmers and easy to implement for compilers. What makes me
    > most puzzled is the hidden reason for the authors of C++98 to put such
    > counterintuitive restrictions on compilers and on us innocent
    > programmers? What's the WHY behind the C++98 restrictions?


    You *do* know who "authors of C++98" actually are? That's right,
    it's a group effort, and one of the most important parts of said
    group *are* the compiler manufacturers. So technically they put
    the restriction in the standard themselves.

    That said, invoking templates with local types can create new
    nightmares considering the proper handling of type visibility
    and namespaces. Frankly, it does not seem you know too much
    about compiler technicalities and especially about the headaches
    templates can produce implementation-wise, so you should
    perhaps be a bit more cautious about statements like "easy to
    implement". To my ears, it does *not* sound exactly 'easy', and
    maybe it sounded too risky at the time to dictate that all
    compliant compilers had to support the feature. So maybe the
    standards committee decided to play it safe; now it is clear that
    the feature can be implemented in a "clean" way both concerning
    implementation and semantics, so they included it in 0x. But to
    speculate on events 12+ years ago is moot.

    Regards,
    Robert
     
    Robert Fendt, Feb 6, 2010
    #2
    1. Advertising

  3. xmllmx

    xmllmx Guest

    On Feb 6, 10:07 pm, Robert Fendt <> wrote:
    > And thus spake xmllmx <>
    > Sat, 6 Feb 2010 04:13:32 -0800 (PST):
    >
    > > Obviously, both of the most popular C++ compiler and C++0x relax the
    > > restrictions put by C++98.

    >
    > To call VC++ the "most popular C++ compiler" is actually quite a
    > bold statement. That holds true only if your entire world
    > consists of Win32 desktop applications. Other compilers like
    > Comeau, Intel and GCC exist not without reason. Especially GCC,
    > which supports nearly any platform on the *planet*. If you look
    > at other domains like embedded systems, POSIX, scientific
    > computing etc. you will find that your "most popular" compiler
    > is more or less useless in every single one of them.
    >
    > > In my view, the new rules without restrictions are intuitive, easy to
    > > use for programmers and easy to implement for compilers. What makes me
    > > most puzzled is the hidden reason for the authors of C++98 to put such
    > > counterintuitive restrictions on compilers and on us innocent
    > > programmers? What's the WHY behind the C++98 restrictions?

    >
    > You *do* know who "authors of C++98" actually are? That's right,
    > it's a group effort, and one of the most important parts of said
    > group *are* the compiler manufacturers. So technically they put
    > the restriction in the standard themselves.
    >
    > That said, invoking templates with local types can create new
    > nightmares considering the proper handling of type visibility
    > and namespaces. Frankly, it does not seem you know too much
    > about compiler technicalities and especially about the headaches
    > templates can produce implementation-wise, so you should
    > perhaps be a bit more cautious about statements like "easy to
    > implement". To my ears, it does *not* sound exactly 'easy', and
    > maybe it sounded too risky at the time to dictate that all
    > compliant compilers had to support the feature. So maybe the
    > standards committee decided to play it safe; now it is clear that
    > the feature can be implemented in a "clean" way both concerning
    > implementation and semantics, so they included it in 0x. But to
    > speculate on events 12+ years ago is moot.
    >
    > Regards,
    > Robert


    I'm sorry for my regarding VC++ as "the most popular C++ compiler". I
    think I should rephrase it as "one of the mainstream C++ compilers".

    Your explanation about this issue is acceptable.

    Thank you very much.
     
    xmllmx, Feb 6, 2010
    #3
  4. xmllmx

    Bo Persson Guest

    Re: Why A Big Difference between C++98 and C++0x on a local type as a template-argument?

    xmllmx wrote:
    > Dear all,
    >
    > C++98 14.3.1 explicitly says as follows:
    >
    > "A local type, a type with no linkage, an unnamed type or a type
    > compunded from any of these types shall not be used as a template-
    > argument for a template type-parameter."
    >
    > And the Standard also immediately gives an example:
    >
    > /*-- Source Code Begin --*/
    >
    > template <class T> class X {};
    >
    > void f()
    > {
    > struct S {};
    >
    > X<S> x3; // error: local type used as template-argument
    > }
    >
    > /*-- Source Code End --*/
    >
    > Nevertheless, the source code should can be correctly compiled by
    > Visual C++. Moreover, C++0x 14.4.1 explicitly says differently as
    > follows:
    >
    > "A template-argument for a template-parameter which is a type shall
    > be a type-id."
    >
    > C++0x 14.4.1 also immediately gives some examples as follows:
    >
    > /*-- Source Code Begin --*/
    >
    > template <class T> class X {};
    > template <class T> void f(T t) {}
    > struct {} unnamed_obj;
    >
    > void f()
    > {
    > struct A {};
    > enum { e1 };
    > typedef struct { } B;
    > B b;
    > X<A> x1; // OK
    > X<A*> x2; // OK
    > X<B> x3; // OK
    > f(e1); // OK
    > f(unnamed_obj); // OK
    > f(b); // OK
    > }
    >
    > /*-- Source Code End --*/
    >
    > Obviously, both of the most popular C++ compiler and C++0x relax the
    > restrictions put by C++98.
    >
    > In my view, the new rules without restrictions are intuitive, easy
    > to use for programmers and easy to implement for compilers. What
    > makes me most puzzled is the hidden reason for the authors of C++98
    > to put such counterintuitive restrictions on compilers and on us
    > innocent programmers? What's the WHY behind the C++98 restrictions?
    >


    The restriction was there beacuse nobody spent enough time to figure
    out what it should mean. If you have two struct S in two different
    functions, will that get you one or two X<S>'s?

    10 years later, the committee has figured this out , and agreed that

    template <class T> class X {};

    void f()
    {
    struct S {};

    X<S> x3; // error: local type used as template-argument
    }

    can be compiled as

    template <class T> class X {};

    namespace
    {
    struct S {};
    }

    void f()
    {
    X<S> x3; // error: local type used as template-argument
    }


    which has been legal and well defined all along.



    Bo Persson
     
    Bo Persson, Feb 6, 2010
    #4
  5. Re: Why A Big Difference between C++98 and C++0x on a local typeas a template-argument?

    On 06/02/10 16:55, Bo Persson wrote:
    > xmllmx wrote:
    >> Dear all,
    >>
    >> C++98 14.3.1 explicitly says as follows:
    >>
    >> "A local type, a type with no linkage, an unnamed type or a type
    >> compunded from any of these types shall not be used as a template-
    >> argument for a template type-parameter."
    >>
    >> And the Standard also immediately gives an example:
    >>
    >> /*-- Source Code Begin --*/
    >>
    >> template<class T> class X {};
    >>
    >> void f()
    >> {
    >> struct S {};
    >>
    >> X<S> x3; // error: local type used as template-argument
    >> }
    >>
    >> /*-- Source Code End --*/
    >>
    >> Nevertheless, the source code should can be correctly compiled by
    >> Visual C++. Moreover, C++0x 14.4.1 explicitly says differently as
    >> follows:
    >>
    >> "A template-argument for a template-parameter which is a type shall
    >> be a type-id."
    >>
    >> C++0x 14.4.1 also immediately gives some examples as follows:
    >>
    >> /*-- Source Code Begin --*/
    >>
    >> template<class T> class X {};
    >> template<class T> void f(T t) {}
    >> struct {} unnamed_obj;
    >>
    >> void f()
    >> {
    >> struct A {};
    >> enum { e1 };
    >> typedef struct { } B;
    >> B b;
    >> X<A> x1; // OK
    >> X<A*> x2; // OK
    >> X<B> x3; // OK
    >> f(e1); // OK
    >> f(unnamed_obj); // OK
    >> f(b); // OK
    >> }
    >>
    >> /*-- Source Code End --*/
    >>
    >> Obviously, both of the most popular C++ compiler and C++0x relax the
    >> restrictions put by C++98.
    >>
    >> In my view, the new rules without restrictions are intuitive, easy
    >> to use for programmers and easy to implement for compilers. What
    >> makes me most puzzled is the hidden reason for the authors of C++98
    >> to put such counterintuitive restrictions on compilers and on us
    >> innocent programmers? What's the WHY behind the C++98 restrictions?
    >>

    >
    > The restriction was there beacuse nobody spent enough time to figure
    > out what it should mean. If you have two struct S in two different
    > functions, will that get you one or two X<S>'s?
    >
    > 10 years later, the committee has figured this out , and agreed that
    >
    > template<class T> class X {};
    >
    > void f()
    > {
    > struct S {};
    >
    > X<S> x3; // error: local type used as template-argument
    > }
    >
    > can be compiled as
    >
    > template<class T> class X {};
    >
    > namespace
    > {
    > struct S {};
    > }
    >
    > void f()
    > {
    > X<S> x3; // error: local type used as template-argument
    > }
    >
    >
    > which has been legal and well defined all along.


    What about the case when there is another function defining struct S.
    They would be different types S, right? I.e. it is not quite like
    putting another S in the same anonymous namespace.

    --
    Max
     
    Maxim Yegorushkin, Feb 6, 2010
    #5
  6. xmllmx

    Bo Persson Guest

    Re: Why A Big Difference between C++98 and C++0x on a local type as a template-argument?

    Maxim Yegorushkin wrote:
    > On 06/02/10 16:55, Bo Persson wrote:
    >> xmllmx wrote:
    >>> Dear all,
    >>>
    >>> C++98 14.3.1 explicitly says as follows:
    >>>
    >>> "A local type, a type with no linkage, an unnamed type or a type
    >>> compunded from any of these types shall not be used as a template-
    >>> argument for a template type-parameter."
    >>>
    >>> And the Standard also immediately gives an example:
    >>>
    >>> /*-- Source Code Begin --*/
    >>>
    >>> template<class T> class X {};
    >>>
    >>> void f()
    >>> {
    >>> struct S {};
    >>>
    >>> X<S> x3; // error: local type used as template-argument
    >>> }
    >>>
    >>> /*-- Source Code End --*/
    >>>
    >>> Nevertheless, the source code should can be correctly compiled by
    >>> Visual C++. Moreover, C++0x 14.4.1 explicitly says differently as
    >>> follows:
    >>>
    >>> "A template-argument for a template-parameter which is a type
    >>> shall be a type-id."
    >>>
    >>> C++0x 14.4.1 also immediately gives some examples as follows:
    >>>
    >>> /*-- Source Code Begin --*/
    >>>
    >>> template<class T> class X {};
    >>> template<class T> void f(T t) {}
    >>> struct {} unnamed_obj;
    >>>
    >>> void f()
    >>> {
    >>> struct A {};
    >>> enum { e1 };
    >>> typedef struct { } B;
    >>> B b;
    >>> X<A> x1; // OK
    >>> X<A*> x2; // OK
    >>> X<B> x3; // OK
    >>> f(e1); // OK
    >>> f(unnamed_obj); // OK
    >>> f(b); // OK
    >>> }
    >>>
    >>> /*-- Source Code End --*/
    >>>
    >>> Obviously, both of the most popular C++ compiler and C++0x relax
    >>> the restrictions put by C++98.
    >>>
    >>> In my view, the new rules without restrictions are intuitive, easy
    >>> to use for programmers and easy to implement for compilers. What
    >>> makes me most puzzled is the hidden reason for the authors of
    >>> C++98 to put such counterintuitive restrictions on compilers and
    >>> on us innocent programmers? What's the WHY behind the C++98
    >>> restrictions?

    >>
    >> The restriction was there beacuse nobody spent enough time to
    >> figure out what it should mean. If you have two struct S in two
    >> different functions, will that get you one or two X<S>'s?
    >>
    >> 10 years later, the committee has figured this out , and agreed
    >> that template<class T> class X {};
    >>
    >> void f()
    >> {
    >> struct S {};
    >>
    >> X<S> x3; // error: local type used as template-argument
    >> }
    >>
    >> can be compiled as
    >>
    >> template<class T> class X {};
    >>
    >> namespace
    >> {
    >> struct S {};
    >> }
    >>
    >> void f()
    >> {
    >> X<S> x3; // error: local type used as template-argument
    >> }
    >>
    >>
    >> which has been legal and well defined all along.

    >
    > What about the case when there is another function defining struct
    > S. They would be different types S, right? I.e. it is not quite like
    > putting another S in the same anonymous namespace.


    I guess they would have to be the same S, if they are in the same
    source file. If they are in different compilation units, they will get
    unique names from the anonymous namespaces.

    The possible non-uniqueness of the template instantiation was the
    original problem.


    Bo Persson
     
    Bo Persson, Feb 6, 2010
    #6
  7. xmllmx

    James Kanze Guest

    On Feb 6, 4:55 pm, "Bo Persson" <> wrote:
    > xmllmx wrote:


    > > C++98 14.3.1 explicitly says as follows:


    [...]
    > > In my view, the new rules without restrictions are intuitive, easy
    > > to use for programmers and easy to implement for compilers. What
    > > makes me most puzzled is the hidden reason for the authors of C++98
    > > to put such counterintuitive restrictions on compilers and on us
    > > innocent programmers? What's the WHY behind the C++98 restrictions?


    > The restriction was there beacuse nobody spent enough time to figure
    > out what it should mean. If you have two struct S in two different
    > functions, will that get you one or two X<S>'s?


    I don't think that there was ever any question concerning what
    it should mean. Classes defined in separate functions are
    distinct types, and always have been, so distinct instantiations
    are needed.

    There was some question concerning how this could or should be
    implemented. A class defined inside a function isn't visible
    outside the function, so how could a template instantiation
    refer to its members.

    > 10 years later, the committee has figured this out , and agreed that


    > template <class T> class X {};


    > void f()
    > {
    > struct S {};
    > X<S> x3; // error: local type used as template-argument
    > }


    > can be compiled as


    > template <class T> class X {};


    > namespace
    > {
    > struct S {};
    > }


    > void f()
    > {
    > X<S> x3; // error: local type used as template-argument
    > }


    > which has been legal and well defined all along.


    It's a bit more complicated than that. What happens if you have
    two functions in the same translation unit which both define a
    class S?

    I think that the real reason had to do with implementability.
    At the time the last revision of the standard was being
    finalized, most template implementations used something more or
    less similar to textual replacement, and there was probably some
    worry that such systems couldn't cope with elements that were
    out of scope.

    --
    James Kanze
     
    James Kanze, Feb 7, 2010
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. jakk
    Replies:
    4
    Views:
    12,511
  2. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,134
    Smokey Grindel
    Dec 2, 2006
  3. steve yee
    Replies:
    5
    Views:
    363
    Bo Persson
    Jul 1, 2008
  4. Shaguf
    Replies:
    0
    Views:
    539
    Shaguf
    Dec 24, 2008
  5. Shaguf
    Replies:
    0
    Views:
    496
    Shaguf
    Dec 26, 2008
Loading...

Share This Page