# C++0x - a few doubts

This is a discussion on C++0x - a few doubts within the C++ Programming forums, part of the General Programming Boards category; Hopefully by 2008 we will have ISO sanctioning C++0x into C++09. By 2009 (most probably even before ratification) some of ...

1. ## 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?

2. 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.

3. 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.

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.

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++.

4. 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...

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.

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.

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.

5. ## 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.

>> 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.

6. Originally Posted by CornedBee
Uh ... there is no such type as an unsigned long double.
My emphasis.

7. 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!

8. 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

9. 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...

10. > 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.

11. >>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

12. 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"?

13. 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!!

14. 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.

15. 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.

Page 1 of 3 123 Last