Thread: C++0x - a few doubts

  1. #1
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446

    C++0x - a few doubts

    Hopefully by 2008 we will have ISO sanctioning C++0x into C++09. By 2009 (most probably even before ratification) some of the new features will start to make their way into compilers. I've been reading about the proposed changes. A couple of things do strike me as odd though. I would like your shared thoughts and help in understanding perhaps some of the choices.

    Concepts
    The notion of concepts seems to me pretty simple. It's the type of a type. Seems to be a push into making the STL more OO oriented which is fine.... I think (I really never understood why some coders insist to believe it's bad the STL is not OO). Anyways, it will be possible to do things like:

    Code:
    std::vector<int> foo;
    /* ... vector populated here ... */
    for_each( foo, add<int>(2) );
    Simply, most algorithms will be overloaded to accept the notion of Concept. On the case of for each, it's quiet possible that the above example will be possible through the overload

    Code:
    UnaryFunction for_each( Container c, UnaryFunction f );
    That type, "Container", is the so called Concept. It seems it will be nothing more than an abstract class of which the container types will derive. Other concepts will probably be Iterator and possibly(?) more specialized versions of the Container concept, like SequencialContainer(?) and AssociativeContainer(?).

    But...

    Will this not make templating around STL objects harder to achieve? There cannot be many assumptions about the type inside the templated function or class. STL objects are invariably very different objects among themselves. So, it seems to me almost useless to create a template with Concept parameters. In fact, it seems a recipe for disaster except for very specific situations that perhaps wouldn't warrant such a big change to the STL.

    Also, will this not add a lot of weight to the STL performance? Every STL object being now inside a OO structure with a base abstract class, especially when accessed through a pure virtual function, will be leaps and bounds slower than the current design. Won't it?

    Type Inference
    This one boggles me to no end. the auto keyword is dropped of its previous use and is now used to define an object of which type is infered from the initializer. So...

    Code:
    int foo = 12;
    auto bar = foo; // bar type is obtained by infering the type of foo. bar is an int.
    From what I have read this is nothing but syntactic sugar. Sure it will help on situations like:

    Code:
    for(std::vector< mjf::calculus::real<int> >::iterator iter = vec.begin(); iter != end(); ++iter)
    
    // where the alternative will be
    
    for(auto iter = vec.begin(); iter != end(); ++iter)
    But...

    What will distinguish const_iterator from iterator? Surely not the compiler! Will it?

    And what more... literals. What to say of auto x = 12.5? It seems logic to believe that the implicit conversion rules will dictate the type of x. But according to these rules x would be a unsigned long double. Highly excessive, don't you think?

    It will also introduce yet another machine dependant construct. But what makes this one worst is that the auto keyword will explicitly hide the type of the object... forever! Only through RTTI will it be possible to effectively debug the code. Worst, there's no RTTI for built-in types. So... What on earth! Am I missing something?

    But more importantly, and this is what boggles me more, will this not break backwards compatibility with C?
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  2. #2
    Registered User
    Join Date
    Nov 2001
    Posts
    255
    most of that is too advanced for me but the last part you dont want backwards compaitibility with C if so that is probably one of the dumbest things ive ever heard.

    though the auto assign variable type thing should be a bit smaller

    but the vectors no idea what they are so no comment.
    hooch

  3. #3
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Quote Originally Posted by Mario F.
    Concepts
    The notion of concepts seems to me pretty simple. It's the type of a type.
    Not strictly correct. A concept is a set of assumptions that are made about a type. These assumptions are formalized as a set of nested types in the type, operations you can perform on the type, and similar. However, the documentation of a concept will usually carry additional semantic requirements on these operations.
    If you're familiar with Java-like, .Net-like or COM-like interfaces, a concept could be called a compile-time interface.

    That type, "Container", is the so called Concept. It seems it will be nothing more than an abstract class of which the container types will derive.
    It's not a base class or abstract class or anything like that. Concepts are purely compile-time constructs, enforced for template parameters at compile time. Several different template parameters will still spawn several instantiations, even if they conform to the same concept. The for_each implementations might look like this:
    Code:
    template<typename InIt, typename Fn> where <InputIterator<InIt>, UnaryFunction<Fn>>
    Fn for_each(InIt first, InIt last, Fn fn)
    {
      for( ; first != last; ++first) fn(*first);
      return fn;
    }
    
    template<typename Rng, typename Fn> where <InputRange<Rng>, UnaryFunction<Fn>>
    Fn for_each(Rng rng, Fn fn)
    {
      return for_each(rng.begin(), rng.end(), fn);
    }
    Pass in a container, and the compiler will notice that it conforms to the InputRange concept (it has a begin() and an end(), both of which return InputIterators), so it will choose the second overload. It will then instantiate a version that is specific to that particular container. No runtime switches.

    Other concepts will probably be Iterator and possibly(?) more specialized versions of the Container concept, like SequencialContainer(?) and AssociativeContainer(?).
    And many refinements of Iterator, and Range and its refinements, and of course all the concepts you can define yourself. Not to mention DefaultConstructible, CopyConstructible, Assignable, and many other things that make useful restrictions on arguments to the STL.

    Will this not make templating around STL objects harder to achieve?
    I don't see how.

    There cannot be many assumptions about the type inside the templated function or class.
    Perhaps, but the purpose of concepts is to document the assumptions that are valid, and enforce them.

    STL objects are invariably very different objects among themselves. So, it seems to me almost useless to create a template with Concept parameters.
    Not at all! Consider what happens if I pass my own custom class ostream_range to for_each. ostream_range has begin() and end(), which return ostream_iterators. ostream_iterators, as is obvious, conform to the OutputIterator concept. Thus, ostream_range conforms to the OutputRange object.
    OK, what happens on a C++98 compiler, which has the above overloads of for_each, but no concept checking - it relies on the argument count for the overload.
    Most likely, I'll get an error message from inside the three-argument for_each, which says something like
    Code:
    ERROR C9783 C:\long\path\to\standard\includes\algorithm (214): Cannot convert
        std::ostream_iterator<_Element>::__assign_proxy to int - no appropriate conversion operator found
      with
      [
        _Element = int
      ]
    C:\long\path\to\standard\includes\algorithm (212): in std::for_each(_InIt __first, _InIt __last, _Fn __fn)
      with
      [
        _InIt = std::ostream_iterator<int>,
        _Fn = void (*)(int)
      ]
    C:\long\path\to\standard\includes\algorithm (227): instantiated from std::for_each(_Rng __rng, _Fn __fn)
      with
      [
        _Rng = cornedbee::tools::ostream_range<int>,
        _Fn = void (*)(int)
      ]
    D:\work\projects\example\faulty.cpp (44): instantiated from here
    And I'm like, Huh?

    Now let's take the C++0x compiler and see what it gives me:
    Code:
    ERROR C8320 D:\work\projects\example\faulty.cpp (44): Cannot pass orng to std::for_each(_Rng __rng, _Fn __fn):
        Object does not fulfill the InputRange concept.
    A lot more informative, wouldn't you say?

    In fact, it seems a recipe for disaster except for very specific situations that perhaps wouldn't warrant such a big change to the STL.
    Where is the danger?

    Also, will this not add a lot of weight to the STL performance? Every STL object being now inside a OO structure with a base abstract class, especially when accessed through a pure virtual function, will be leaps and bounds slower than the current design. Won't it?
    It won't. As I said, concepts are a purely compile-time mechanism. There is no trace of them left at runtime.

    Type Inference
    This one boggles me to no end. the auto keyword is dropped of its previous use
    Not that I know of. I don't think it was ever valid to use the auto storage modifier without an actual type. It will still exist as a storage modifier. (As such, "auto auto" should be valid.)

    and is now used to define an object of which type is infered from the initializer. So...

    Code:
    int foo = 12;
    auto bar = foo; // bar type is obtained by infering the type of foo. bar is an int.
    From what I have read this is nothing but syntactic sugar.
    Indeed. Very, very important syntactic sugar, if you've ever played with complicated types like Boost.Spirit's parsers.

    What will distinguish const_iterator from iterator? Surely not the compiler! Will it?
    Nothing does. Except this: right now, hardly anybody uses const_iterator if the source object isn't const, because it's too much to write. If the object IS const, then the compiler will correctly deduct const_iterator for auto. The non-const version of begin() won't be considered, because the object is const.
    Also, there's a proposal to add cbegin() and cend() etc. to all containers that are not overloaded on constness. I'm not sure if that proposal will go through.

    And what more... literals. What to say of auto x = 12.5? It seems logic to believe that the implicit conversion rules will dictate the type of x. But according to these rules x would be a unsigned long double. Highly excessive, don't you think?
    Uh ... there is no such type as an unsigned long double. The type of a suffix-less decimal constant expression is double, and that will be the deduced type of x, too. There's absolutely no ambiguity there, and no implicit conversion rules come into play. The nice thing about auto is that you're guaranteed there won't be any conversion on initialization.

    It will also introduce yet another machine dependant construct.
    No, it isn't at all machine-dependent. The types of literals are well-defined by the standard.

    But what makes this one worst is that the auto keyword will explicitly hide the type of the object... forever! Only through RTTI will it be possible to effectively debug the code. Worst, there's no RTTI for built-in types. So... What on earth! Am I missing something?
    You can just do the same as the compiler does and deduce the type of the object from its initializer.

    But more importantly, and this is what boggles me more, will this not break backwards compatibility with C?
    No. As I said, the auto keyword will retain its functionality as a storage modifier.

    Quote Originally Posted by ssjnamek
    most of that is too advanced for me but the last part you dont want backwards compaitibility with C if so that is probably one of the dumbest things ive ever heard.
    You might want to be very careful with such statements. Backwards compatibility always was and still is a stated goal of C++.
    Last edited by CornedBee; 09-18-2006 at 04:58 PM.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  4. #4
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Quote Originally Posted by CornedBee
    Not strictly correct. A concept is a set of assumptions that are made about a type.
    Wow! I was definitely not expecting such a comprehensive reply, CornedBee. Many thanks
    I will definitely take this as reference material. It's saved!

    I was limiting my understanding of Concepts as merely asbtract classes. Now, everything makes a lot more sense. Many, many thanks again.

    But... the other matter hehe...

    Quote Originally Posted by CornedBee
    I don't think it was ever valid to use the auto storage modifier without an actual type. It will still exist as a storage modifier. (As such, "auto auto" should be valid.)
    Aha! Of course! Didn't think of that.
    However... it has to be said that the choice of keyword name is somewhat debatable, in my opinion. Here you have the same keyword with completely different meanings depending on the semantics associated. The only other two keywords I know that do this is static and class... and class still only exists as a template parameter keyword probably because of backwards compatibility.

    Quote Originally Posted by CornedBee
    Uh ... there is no such type as an unsigned long double.
    hmm... I urge you to read the ISO... give me a sec... 3.9.1.8.
    And I was pretty much convinced this was the default type of floating literals (with no suffix) since from float is a subset of double, which is a subset of long double. Granted, some compilers may not implement long double or implement it with the same precision of double. MinGW, for instance, recognizes long double as being double.

    Regardless, it doesn't matter. I was wrong in assuming default conversions would have a saying about what type would defined auto variables initialized from literals. You explained variables are not initialized like that The standard defines them.

    Quote Originally Posted by CornedBee
    You can just do the same as the compiler does and deduce the type of the object from its initializer.
    Yes. I understand that now since i finally have an understanding of literal types. But that doesn't really give me much comfort for user-defined types. Here, I see trouble debugging unexpected runtime results.
    Last edited by Mario F.; 09-18-2006 at 06:19 PM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  5. #5
    semi-colon generator ChaosEngine's Avatar
    Join Date
    Sep 2005
    Location
    Chch, NZ
    Posts
    597

    auto keyword

    I'm not really concerned with dropping the "auto" keyword as it is used now. most compilers have deprecated it anyway.

    but I can't wait for the new "auto-type" functionality. first, it's not really designed to be used in simple cases ala
    Code:
    auto x = 5;
    but it will be stunningly useful for things like boost.bind
    Code:
    class MyClass
    {
        void DoStuff(int x);
    };
    MyClass c;
    
    // would you prefer
    boost::bind<void, MyClass::*, MyClass &, int> func = boost::bind(&MyClass::DoStuff, c, _1);
    
    // or 
    auto func = boost::bind(&MyClass::DoStuff, c, _1);
    and once you get into templated functions it'll allow you to do things that would be otherwise impossible.

    Code:
    template <typename F, typename arg>
    void TestAndPrintFuncResult(F f, arg a1)
    {
        // only want to call f once
        auto x = f(a1);
    
        // do stuff with x
        // ....
    
    
        cout << x;
    }
    as for concepts, try boost's concept checking library with your template code. It makes tracking errors so much easier. If language support can improve on that, I'm all for it.

    [edit]
    >> hmm... I urge you to read the ISO... give me a sec... 3.9.1.8.
    There are three floating point types: float, double, and long double. The type double provides
    at least as much precision as float, and the type long double provides at least as much precision as
    double. The set of values of the type float is a subset of the set of values of the type double; the set
    of values of the type double is a subset of the set of values of the type long double. The value representation
    of floating-point types is implementation-defined. Integral and floating types are collectively
    called arithmetic types. Specializations of the standard template numeric_limits (18.2) shall specify
    the maximum and minimum values of each arithmetic type for an implementation.
    There is a long double, but unless I've read it wrong there's nothing about an unsigned double.
    Last edited by ChaosEngine; 09-18-2006 at 06:26 PM.
    "I saw a sign that said 'Drink Canada Dry', so I started"
    -- Brendan Behan

    Free Compiler: Visual C++ 2005 Express
    If you program in C++, you need Boost. You should also know how to use the Standard Library (STL). Want to make games? After reading this, I don't like WxWidgets anymore. Want to add some scripting to your App?

  6. #6
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by CornedBee
    Uh ... there is no such type as an unsigned long double.
    My emphasis.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  7. #7
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Quote Originally Posted by Dave_Sinkula
    My emphasis.
    Duh! *blush*
    I have no idea why I put that there!
    Even more embarassing... I replied to it!
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  8. #8
    Registered User
    Join Date
    Nov 2001
    Posts
    255
    You might want to be very careful with such statements. Backwards compatibility always was and still is a stated goal of C++.

    pretty sure i said removing backwards compaitibility was a dumb idea since thats what i thought the original poster of this thread is saying
    hooch

  9. #9
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Quote Originally Posted by ChaosEngine
    Code:
    // would you prefer
    boost::bind<void, MyClass::*, MyClass &, int> func = boost::bind(&MyClass::DoStuff, c, _1);
    
    // or 
    auto func = boost::bind(&MyClass::DoStuff, c, _1);
    Definitely the second. And with boost::bind being my 3rd favorite boost library... (I need a life).

    However, I'm also concerned with possible side-effects. Namely the "wrong" type being attributed to the object. It is though a fact that I'll be a smart arse if I try to use auto for anything other than just simplify those type of variable declarations, that are apparently easy to debug. Or won't I? And that is the problem...
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  10. #10
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    > pretty sure i said removing backwards compaitibility was a dumb idea since thats what i thought the original poster of this thread is saying

    No. On the contrary. I was showing concern over that.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  11. #11
    The Richness... Richie T's Avatar
    Join Date
    Jan 2006
    Location
    Ireland
    Posts
    469
    >>pretty sure i said removing backwards compaitibility was a dumb idea since thats what i thought the original poster of this thread is saying

    You misinterpreted - mario was questioning as to whether the new functionality was going to make old C code invalid.

    Try reading a little more carefully before agreeing to whatever someone else says - and shooting your mouth off as well.

    Back on topic - these new features seem quite high level - the language just keeps on growing
    No No's:
    fflush (stdin); gets (); void main ();


    Goodies:
    Example of fgets (); The FAQ, C/C++ Reference


    My Gear:
    OS - Windows XP
    IDE - MS Visual C++ 2008 Express Edition


    ASCII stupid question, get a stupid ANSI

  12. #12
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    You want to know my favorite? (for purely academic reasons)

    You will be able to initialize sequence containers like:

    Code:
    vector<int> vec = {1, 2, 3, 4, 5};
    Can you say with me "No more use vector instead of array posts"?
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  13. #13
    semi-colon generator ChaosEngine's Avatar
    Join Date
    Sep 2005
    Location
    Chch, NZ
    Posts
    597
    Quote Originally Posted by Mario F.
    You want to know my favorite? (for purely academic reasons)

    You will be able to initialize sequence containers like:

    Code:
    vector<int> vec = {1, 2, 3, 4, 5};
    Can you say with me "No more use vector instead of array posts"?
    I hadn't seen that before! that's awesome!!
    "I saw a sign that said 'Drink Canada Dry', so I started"
    -- Brendan Behan

    Free Compiler: Visual C++ 2005 Express
    If you program in C++, you need Boost. You should also know how to use the Standard Library (STL). Want to make games? After reading this, I don't like WxWidgets anymore. Want to add some scripting to your App?

  14. #14
    Registered User
    Join Date
    Nov 2001
    Posts
    255
    Quote Originally Posted by Mario F.
    > pretty sure i said removing backwards compaitibility was a dumb idea since thats what i thought the original poster of this thread is saying

    No. On the contrary. I was showing concern over that.
    ah gotcha

    and i had already said i wasnt sure if thats what he ment cause it sounded al ittle to advanced for me since i have no clue what vectors are yet richie_t just if thats what he ment it was a dumb idea.
    hooch

  15. #15
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Concepts are a part of the current STL, although as Dave said, they are not checked by the compiler. There is an introduction and a list.

    Is concept checking a worthwhile feature? I would have thought that programmers implementing an STL concept (how often is this done anyway?) would be fairly experienced and not require hand holding by the compiler.

    I haven't read the draft standards, so it is quite possible that I'm missing something. I hope C++ doesn't go in the direction of C99, which is complex enough that there are very few complete implementations.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Doubts regarding random numbers generation
    By girish1026 in forum C Programming
    Replies: 9
    Last Post: 12-31-2008, 10:47 PM
  2. More questions (relating to global doubts)
    By Jorl17 in forum C++ Programming
    Replies: 29
    Last Post: 12-03-2008, 11:40 AM
  3. Some doubts on DLLs
    By BrownB in forum Windows Programming
    Replies: 1
    Last Post: 05-30-2007, 02:25 AM
  4. Two doubts about C for my project
    By j0nnyX in forum C Programming
    Replies: 4
    Last Post: 10-11-2004, 02:31 PM
  5. doubts on scanf
    By aqua in forum C Programming
    Replies: 1
    Last Post: 10-28-2002, 04:20 AM