Generics in C#, Java, and C++

Discussion in 'C++' started by atgraham@gmail.com, Jan 1, 2006.

  1. Guest

    Here is the "lead C# architect" attempting to impugn C++ templates
    (bottom of the page).

    http://www.artima.com/intv/generics2.html (bottom of the page)
    (Full article begins at http://www.artima.com/intv/generics.html)

    I think every employee at Micrsoft must be required to take a class in
    "FUD marketing" before speaking with anyone outside the company. I
    think the term "money oriented programming" is suitable here.
     
    , Jan 1, 2006
    #1
    1. Advertising

  2. Luke Meyers Guest

    Wow, that's truly appalling. It's a shame that a programming language
    can't sue for libel.

    Luke
     
    Luke Meyers, Jan 2, 2006
    #2
    1. Advertising

  3. Greg Guest

    wrote:
    > Here is the "lead C# architect" attempting to impugn C++ templates
    > (bottom of the page).
    >
    > http://www.artima.com/intv/generics2.html (bottom of the page)
    > (Full article begins at http://www.artima.com/intv/generics.html)
    >
    > I think every employee at Micrsoft must be required to take a class in
    > "FUD marketing" before speaking with anyone outside the company. I
    > think the term "money oriented programming" is suitable here.


    Um, the interview seems neither inaccurate nor the least bit derogatory
    toward C++; so it's hard to see how C++ the language is being
    "impugned."

    Templates in C++ can often replace C macros (look at std::min and
    std::max). But of course doing so would only make sense if templates
    were better than macros, which of course, they are.

    Greg
     
    Greg, Jan 2, 2006
    #3
  4. Luke Meyers Guest

    Greg wrote:
    > Um, the interview seems neither inaccurate nor the least bit derogatory
    > toward C++; so it's hard to see how C++ the language is being
    > "impugned."


    Okay, I'll go into more detail.

    > Templates in C++ can often replace C macros (look at std::min and
    > std::max). But of course doing so would only make sense if templates
    > were better than macros, which of course, they are.


    Right, that's exactly the point. Templates are vastly more expressive
    and useful than macros, so when the article states:

    "C++ templates are really just like macros, except they look like
    classes."

    it's simply untrue. Shortly thereafter, he apparently contradicts
    himself:

    (1) "C# does the instantiation at runtime"
    (2) "C# does strong type checking when you compile the generic type"

    He's referring here to class instantiation, not object instantiation.
    I don't see how you can claim to do strong type checking without
    instantiating the generic. Maybe some parts of it are left for run
    time, but his whole context here is about type-checking, so that's the
    only part that's really relevant.

    Anyway, he uses this as a basis for pointing out that, due to this
    strong type checking at compile time, only valid operations for that
    type are available at runtime. Well, yes, obviously -- otherwise, it
    would fail the compile-time type checking. So again, I don't see how
    he can claim that this is runtime instantiation. Maybe he's confusing
    polymorphism with template instantiation or something?

    He then goes on to use different wording to describe the fact that C++
    also does strong type checking at compile time, but somehow decides
    that the two languages are completely opposite in this regard:

    "In C++, you can do anything you damn well please on a variable of a
    type parameter type. But then once you instantiate it, it may not work,
    and you'll get some cryptic error messages... So in a sense, C++
    templates are actually untyped, or loosely typed. Whereas C# generics
    are strongly typed."

    It's a valid criticism that C++ template error messages are sometimes
    verbose and difficult, but that's a red herring (besides, how do C#
    error messages compare in similarly complex cases?). Both C++ and C#
    provide compile-time type-checking of templates. If there is an error,
    the compiler will report it. What he's doing here is interpreting this
    behavior completely differently in each case. For C#, all he does is
    talk up the wonderful guarantees provided by this checking, completely
    glossing over the fact that, of course, C# must also generate error
    messages if the type checking fails. For C++, he interprets the exact
    same behavior as a failure, a complete lack of a type system. The
    error messages are EXACTLY how you get strong type-checking! It's the
    earliest possible opportunity, short of IDE integration, to check that
    the operations performed on a parameterized type are valid. The
    compiler will not let you proceed if you have type errors in your code
    -- that IS strong type checking! His lack of understanding of the
    terms he's using is further indicated by the phrase "in a sense" -- did
    the definition of "strongly typed" suddenly become subjective? It's
    the same as the obviously deceptive "from a certain point of view" sort
    of reasoning.

    It's absurd, it's false, it's misinformed, it's FUD. Engage your brain
    and read it until you realize this.

    Luke
     
    Luke Meyers, Jan 2, 2006
    #4
  5. Mirek Fidler Guest

    wrote:
    > Here is the "lead C# architect" attempting to impugn C++ templates
    > (bottom of the page).
    >
    > http://www.artima.com/intv/generics2.html (bottom of the page)
    > (Full article begins at http://www.artima.com/intv/generics.html)
    >
    > I think every employee at Micrsoft must be required to take a class in
    > "FUD marketing" before speaking with anyone outside the company. I
    > think the term "money oriented programming" is suitable here.
    >

    Well, I guess that something really stinks there:

    "Difference number two is C# does strong type checking when you compile
    the generic type. For an unconstrained type parameter, like List<T>, the
    only methods available on values of type T are those that are found on
    type Object,"

    "C++ is the opposite. In C++, you can do anything you damn well please
    on a variable of a type parameter type. But then once you instantiate
    it, it may not work, and you'll get some cryptic error messages. For
    example, if you have a type parameter T, and variables x and y of type
    T, and you say x + y, well you had better have an operator+ defined for
    + of two Ts, or you'll get some cryptic error message.

    Actually, for me it looks like "the opposite". C# seems to do no strong
    type checking (because the only type allowed in template code is
    Object, that is equivalent of "void *"), whereas C++ does it (beacause
    compiler emits "cryptic" error messages for invalid operations at the
    runtime).

    I guess somebody should explain to C# inventor what is strong type
    checking :)

    Mirek
     
    Mirek Fidler, Jan 2, 2006
    #5
  6. Mirek Fidler Guest


    > compiler emits "cryptic" error messages for invalid operations at the
    > runtime).


    *compile time*

    Sorry :)

    Mirek
     
    Mirek Fidler, Jan 2, 2006
    #6
  7. Mirek Fidler Guest

    > error messages compare in similarly complex cases?). Both C++ and C#
    > provide compile-time type-checking of templates.


    Actually, from what I have read, C# seems to provide "void *" level of
    checking... (of course, with GC langauge, void * is more useful and
    Object prehaps has more useful properties than void *, but in the end,
    it is just this...)

    Mirek
     
    Mirek Fidler, Jan 2, 2006
    #7
  8. Guest

    Very well said, Luke!

    You got most of it, but you left out this part:

    "C# generics are really just like classes, except they have a type
    parameter. C++ templates are really just like macros, except they look
    like classes."

    He "forgets" to point out here that C# generics are much more limited
    than C++ templates. C++ templates aren't just limited to classes, and
    C++ template parameters aren't limited to typenames.

    Just like in Java, C# generics are just a way to provide another bullet
    point for the language feature set. I wonder if the "lead C#
    architect" actually thought he could improve on C++ templates (if that
    could have been done, wouldn't the C++ committee have done it?), or if
    he just didn't realize why generic programming is important:

    "It is silly to abstract an algorithm in such a way that when you
    instantiate it back it becomes inefficient." - Alex Stepanov

    Aaron
     
    , Jan 2, 2006
    #8
  9. Luke Meyers Guest

    > "It is silly to abstract an algorithm in such a way that when you
    > instantiate it back it becomes inefficient."


    Hey, computers keep getting faster! We don't need to code efficiently
    anymore.

    At least, so sayeth the bloaters of code, the havers of sweetheart
    backroom deals with the hardware vendors.

    Cheers.

    Luke

    P.S. Generics ain't templates, but when I'm stuck writing Java I'm
    happier having them than not. As for C#... I don't put myself in that
    position.
    P.P.S. Can we start pronouncing it "See-octothorpe?"
     
    Luke Meyers, Jan 2, 2006
    #9
  10. Greg Guest

    Mirek Fidler wrote:
    > wrote:
    > > Here is the "lead C# architect" attempting to impugn C++ templates
    > > (bottom of the page).
    > >
    > > http://www.artima.com/intv/generics2.html (bottom of the page)
    > > (Full article begins at http://www.artima.com/intv/generics.html)
    > >
    > > I think every employee at Micrsoft must be required to take a class in
    > > "FUD marketing" before speaking with anyone outside the company. I
    > > think the term "money oriented programming" is suitable here.
    > >

    > Well, I guess that something really stinks there:
    >
    > "Difference number two is C# does strong type checking when you compile
    > the generic type. For an unconstrained type parameter, like List<T>, the
    > only methods available on values of type T are those that are found on
    > type Object,"
    >
    > "C++ is the opposite. In C++, you can do anything you damn well please
    > on a variable of a type parameter type. But then once you instantiate
    > it, it may not work, and you'll get some cryptic error messages. For
    > example, if you have a type parameter T, and variables x and y of type
    > T, and you say x + y, well you had better have an operator+ defined for
    > + of two Ts, or you'll get some cryptic error message.
    >
    > Actually, for me it looks like "the opposite". C# seems to do no strong
    > type checking (because the only type allowed in template code is
    > Object, that is equivalent of "void *"), whereas C++ does it (beacause
    > compiler emits "cryptic" error messages for invalid operations at the
    > runtime).


    No, C# does perform type-checking for generics since it ensures that
    the parameterized type specfied is compatible with the declared type,
    in this case, the Object type. In other words, void * would not be
    accepted as a parameter type for C#'s List<> generic while it would be
    accepted for C++'s std::list class template.

    And in fact there is no language supported way to prevent C++'s
    std::list<> (or any template) from being instantiated with void * or
    any other type. C++ simply performs no type checking on the type
    parameter for a class template, so it accepts any type. That is not to
    say that a template can be successfully instantiated with any type. But
    if there is an error instantiating a template with a particular type,
    it is not often clear whether the template or the parameterized type is
    to blame.

    Lack of parameterized type checking is not necessarily a shortcoming of
    C++. Nor is it an argument that C++ should perform such checking
    (though there are proposals to add such support to the language).
    Instead it is simply an inarguable, factual observation that C++ does
    not support this concept.

    Greg
     
    Greg, Jan 2, 2006
    #10
  11. Luke Meyers Guest

    Greg wrote:
    > And in fact there is no language supported way to prevent C++'s
    > std::list<> (or any template) from being instantiated with void * or
    > any other type. C++ simply performs no type checking on the type
    > parameter for a class template, so it accepts any type. That is not to
    > say that a template can be successfully instantiated with any type. But
    > if there is an error instantiating a template with a particular type,
    > it is not often clear whether the template or the parameterized type is
    > to blame.
    >
    > Lack of parameterized type checking is not necessarily a shortcoming of
    > C++. Nor is it an argument that C++ should perform such checking
    > (though there are proposals to add such support to the language).
    > Instead it is simply an inarguable, factual observation that C++ does
    > not support this concept.


    Actually, there are multiple ways to accomplish this. You can't mess
    with std::list, but for your own templates, you have options. If you
    want explicitly specify the types allowed for a template, you can use
    partial template specialization on one or more common base classes. If
    you want to simply exclude certain types, I'd use BOOST_STATIC_ASSERT
    or a similar construct to check against them.

    Luke
     
    Luke Meyers, Jan 3, 2006
    #11
  12. Mirek Fidler Guest

    >>Actually, for me it looks like "the opposite". C# seems to do no strong
    >>type checking (because the only type allowed in template code is
    >>Object, that is equivalent of "void *"), whereas C++ does it (beacause
    >>compiler emits "cryptic" error messages for invalid operations at the
    >>runtime).

    >
    >
    > No, C# does perform type-checking for generics since it ensures that
    > the parameterized type specfied is compatible with the declared type,
    > in this case, the Object type. In other words, void * would not be
    > accepted as a parameter type for C#'s List<> generic while it would be
    > accepted for C++'s std::list class template.


    That is not what I wanted to say.

    The thing is that C# (if I understand things well) allows only Object's
    methods to be called in templated code. That it turn makes is quite
    limited for expressing generic algorithm. It is somewhat similar to
    using "void *" for implementic generics (like that old qsort function of C).

    As long as only Object is supported, the only possible way how to make
    more complicated stuff is casting - and that is hardly "strong type
    checking", it is more "void *" kind of things in compile time.

    But then again, I might misundestand the issue. This is what I got from
    the article.

    Mirek
     
    Mirek Fidler, Jan 3, 2006
    #12
  13. Guest

    Mirek Fidler wrote:
    > >>Actually, for me it looks like "the opposite". C# seems to do no strong
    > >>type checking (because the only type allowed in template code is
    > >>Object, that is equivalent of "void *"), whereas C++ does it (beacause
    > >>compiler emits "cryptic" error messages for invalid operations at the
    > >>runtime).

    > >
    > >
    > > No, C# does perform type-checking for generics since it ensures that
    > > the parameterized type specfied is compatible with the declared type,
    > > in this case, the Object type. In other words, void * would not be
    > > accepted as a parameter type for C#'s List<> generic while it would be
    > > accepted for C++'s std::list class template.

    >
    > That is not what I wanted to say.
    >
    > The thing is that C# (if I understand things well) allows only Object's
    > methods to be called in templated code. That it turn makes is quite
    > limited for expressing generic algorithm. It is somewhat similar to
    > using "void *" for implementic generics (like that old qsort function of C).


    Not true. You can specify a constraint for a template parameter. An
    example from the C# language specification is:

    public class Dictionary<K,V> where K: IComparable
    {
    public void Add(K key, V value)
    {
    ...
    if (key.CompareTo(x) < 0) {...}
    ...
    }
    }

    Becuase of the constraint, we do know something more about K than
    merely that it is an Object. We know it implements IComparable. The
    compiler/runtime can therefore validate the call to CompareTo when
    the template is compiled -- i.e., before it is instantiated.

    > As long as only Object is supported, the only possible way how to make
    > more complicated stuff is casting - and that is hardly "strong type
    > checking", it is more "void *" kind of things in compile time.


    The piece you're missing is how strong type checking interacts with
    constraints.
     
    , Jan 3, 2006
    #13
  14. Shezan Baig Guest

    Greg wrote:
    > Lack of parameterized type checking is not necessarily a shortcoming of
    > C++. Nor is it an argument that C++ should perform such checking
    > (though there are proposals to add such support to the language).
    > Instead it is simply an inarguable, factual observation that C++ does
    > not support this concept.



    This is simply not true. In fact, I would go as far as saying that C++
    supports this concept and much more!

    In C++, I can assert (at compile time) not only whether a type T
    derives from a particular class, but I can also assert all kinds of
    other meta-information (e.g, whether type T is a pointer, is a
    polymorphic type, is a function, is a fundamental type, etc etc)... the
    list goes on and on...

    I find the constraints in C# far too limiting. That's probably a
    result of hardcoding these concepts into the compiler, rather than
    allowing library developers to implement these concepts within library
    code.

    -shez-
     
    Shezan Baig, Jan 4, 2006
    #14
  15. Shezan Baig Guest

    wrote:
    > I wonder if the "lead C#
    > architect" actually thought he could improve on C++ templates (if that
    > could have been done, wouldn't the C++ committee have done it?)



    Well, the C++ committee *is* improving on it. I personally cannot wait
    for Stroustrup's idea of 'concepts'. Being able to specialize a
    template based on a concept is just sweet :) Also, the 'auto' type is
    a *big* improvement.

    -shez-
     
    Shezan Baig, Jan 4, 2006
    #15
  16. Shezan Baig Guest

    wrote:
    > You can specify a constraint for a template parameter. An
    > example from the C# language specification is:
    >
    > public class Dictionary<K,V> where K: IComparable
    > {
    > public void Add(K key, V value)
    > {
    > ...
    > if (key.CompareTo(x) < 0) {...}
    > ...
    > }
    > }
    >
    > Becuase of the constraint, we do know something more about K than
    > merely that it is an Object. We know it implements IComparable. The
    > compiler/runtime can therefore validate the call to CompareTo when
    > the template is compiled -- i.e., before it is instantiated.




    That is interesting. But it still seems to me that without these
    constraints, we are losing some level of type-safety by making 'K' and
    'V' simply 'Object's. For instance, consider this (rather inefficient)
    implementation of a 'Dictionary':


    public class Dictionary<K,V>
    {
    private List<K> keys;
    private List<V> values;

    public void Add(K key, V value)
    {
    keys.Add(value);
    values.Add(key);
    }
    }


    If 'Dictionary' is instantiated with different types for 'K' and 'V',
    then there is obviously a type-mismatch in the 'Add' function. But
    within the scope of 'Dictionary', the types 'K' and 'V' are just
    'Object's. So, I would guess that 'keys' and 'values' are both of type
    'List<Object>' (please correct me if I'm wrong, I'm just inferring this
    based on the article).

    So what I want to know is: how does the compiler know that it should
    generate a type-mismatch error if 'Dictionary' is instantiated with
    different 'K' and 'V' types? Does it just do a lexical comparison of
    the type names?

    If a lexical comparison is used to differentiate them, then how do we
    handle the cases where we *do* want to behave a certain way if we
    detect whether they are the same type? (we are drifting slightly off
    the 'Dictionary' example here, but there are times where we want to
    specialize behaviour based on certain type traits). We could probably
    use reflection, but if we did that, then we might as well not use
    generics since we completely lose *all* compile-time type safety.

    Granted, this is a very simple, silly example - but real code would
    probably be more complicated. The point is this: In a reasonably sized
    generic component, it would be dangerous to lose type information, even
    within the scope of the generic class.

    -shez-
     
    Shezan Baig, Jan 4, 2006
    #16
  17. Guest

    Shezan Baig wrote:
    > wrote:
    > > You can specify a constraint for a template parameter. An
    > > example from the C# language specification is:
    > >
    > > public class Dictionary<K,V> where K: IComparable
    > > {
    > > public void Add(K key, V value)
    > > {
    > > ...
    > > if (key.CompareTo(x) < 0) {...}
    > > ...
    > > }
    > > }
    > >
    > > Becuase of the constraint, we do know something more about K than
    > > merely that it is an Object. We know it implements IComparable. The
    > > compiler/runtime can therefore validate the call to CompareTo when
    > > the template is compiled -- i.e., before it is instantiated.

    >
    > That is interesting. But it still seems to me that without these
    > constraints, we are losing some level of type-safety by making 'K' and
    > 'V' simply 'Object's.


    Not at all, because if you don't specify any constraints it doesn't
    mean "anything goes"; on the contrary, it means you're rather limited
    in what you can do with objects of type 'K' and 'V'.

    > For instance, consider this (rather inefficient)
    > implementation of a 'Dictionary':
    >
    >
    > public class Dictionary<K,V>
    > {
    > private List<K> keys;
    > private List<V> values;
    >
    > public void Add(K key, V value)
    > {
    > keys.Add(value);


    This should be a compile-time error. The keys field is a List<K>
    so its Add method takes a single parameter of type K. Since value
    has type V, the compiler should ask itself, "can I prove that type
    V is convertable to type K?" The answer is no since you specified
    no constraints on either type.

    If you wanted to specifically allow this case you would specify
    the constraint "where V : K".

    > values.Add(key);


    Same as above in reverse.

    > If 'Dictionary' is instantiated with different types for 'K' and 'V',
    > then there is obviously a type-mismatch in the 'Add' function. But
    > within the scope of 'Dictionary', the types 'K' and 'V' are just
    > 'Object's. So, I would guess that 'keys' and 'values' are both of type
    > 'List<Object>' (please correct me if I'm wrong, I'm just inferring this
    > based on the article).


    No, keys and values have types List<K> and List<V>. In the absence of
    constraints, the compiler doesn't know very much about type 'K', but it
    still has an identity; thus the 'K' in List<K> denotes the same type
    as the 'K' in the first parameter to the Add method above.

    You might find the following paper interesting, "The Design and
    Implementation of Generics for the .NET Common Language Runtime":

    http://research.microsoft.com/projects/clrgen/generics.pdf
     
    , Jan 9, 2006
    #17
  18. Shezan Baig Guest

    Shezan Baig, Jan 9, 2006
    #18
    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. Sebastian Millies

    Java Generics, Type Erasure and Frameworks

    Sebastian Millies, Oct 7, 2004, in forum: Java
    Replies:
    1
    Views:
    654
    Chris Uppal
    Oct 7, 2004
  2. Juergen Berchtel
    Replies:
    1
    Views:
    6,008
    John C. Bollinger
    May 20, 2005
  3. Royan
    Replies:
    8
    Views:
    756
    Patricia Shanahan
    Feb 15, 2008
  4. Vikram
    Replies:
    4
    Views:
    528
    Vikram
    Jun 13, 2008
  5. Soul
    Replies:
    0
    Views:
    524
Loading...

Share This Page