Should I use C++0x Features Now?

2019-03-17 11:58发布

问题:

With the official release of VS 2010, is it safe for me to start using the partially-implemented C++0x feature set in my new code?

The features that are of interest to me right now are both implemented by VC++ 2010 and recent versions of GCC. These are the only two that I have to support.

In terms of the "safety" mentioned in the first sentence: can I start using these features (e.g., lambda functions) and still be guaranteed that my code will compile in 10 years on a compiler that properly conforms to C++0x when it is officially released?

I guess I'm asking if there is any chance that VC++ 2010 or GCC will end up like VC++ 6; it was released before the language was officially standardized and consequently allowed grossly ill-formed code to compile.

After all, Microsoft does say that "10 is the new 6". ;)

回答1:

There are several items I've already discovered that are not written to the standard. For instance, this would not work:



struct test {
  int operator()(int);
};

std::cout << typeid( std::result_of<test(int)>::type ).name() << std::endl;

According to the wikipedia site on C++0x it should. Apparently VS2010 uses the TR1 definition of result_of, which is different from what C++0x will have (based on decltype).

Also, this does not work:



std::bind<int>([](int i)->int {return i; });

It fails because calling std::result_of (well, the implementation of it), fails because the lambda type has no result_of typedef. This is of course why you supply the return type to the bind call but apparently it ignores it for some reason and continues to search on its own. The boost version of bind works as expected. For this reason we're continuing to use the boost version of bind in our project.

Also, if you'll note on http://blogs.msdn.com/vcblog/archive/2010/04/06/c-0x-core-language-features-in-vc10-the-table.aspx?CommentPosted=true#commentmessage that there's some changes yet to be implemented by VS2010 that will effect lambda expressions. I haven't been able to break them but then I haven't used nested lambdas and probably never will.

You should also keep in mind that boost::shared_ptr and std::shared_ptr are incompatible. Not surprising, but you must know this if you intend to use one or the other...I'd recommend not both and we're just going to stick with boost.

There's also no declval in VS2010. Easy enough to make though:


template < typename T > T&& declval();

Example of use:


template < typename T >
struct point
{
  T x,y;
};

template < typename T1, typename T2 >
point<decltype(declval<T1>() + declval<T2>())> operator + (point<T1> const& lh, point<T2> const& rh)
{
 ...
}

You'll also note in the page I linked above that I've already discussed with members of the dev team (or the PR part or whatever) that there's a bug in decltype. There's more than just the one I mention so I'll show both:


template < typename T1, typename T2 >
auto operator + (point<T1> const& lh, point<T2> const& rh)
  -> point<decltype(lh.x + rh.x)>
{
...
}
point<int> x; point<double> y;
point<double> pt = x + y; // fails, operator + returned point<const double>

void f();
auto ptr = &f;

std::cout << typeid( decltype(*ptr) ).name() << std::endl;
std::cout << typeid( decltype(*&f) ).name() << std::endl; // should output the same thing...outputs void (*)()

Also...according to some email exchanges about decltype and result_of, this should work:



std::result_of< decltype(f)() >::type x = f();

With my home brewed version of std::result_of that uses decltype this would work if the decltype(f)() expression worked correctly. It does not. Gives some error about function returning a function. You have to use "decltype(&f)()" to make the expression work.

So, sure...we're using it. There's some bugs and crap though. The benefits outweigh waiting IMHO. Don't expect your code to be standard when the standard comes out though and future MS compilers may break it.



回答2:

The C++0X feature set is pretty fixed by now, so I'd say go for it. The final draft of the proposal should be done in august according to wikipedia.

A lot of the things are available from boost anyway (actually, a lot of 0X things come from boost) - see boost TR1. You can re-use those features through boost even if the compiler isn't fully C++0X.



回答3:

Much of the important things (ie things you would typically use often) are pretty much set in stone. I think the risk of writing code that becomes non-standard is extremely low, especially if you stick to a subset of the spec implemented on current compilers.

For a good table listing the support for features go here. Personally auto variables, r-value references, and lambdas are pretty much the big features to use and are well supported.



回答4:

I guess I'm asking if there is any chance that VC++ 2010 or GCC will end up like VC++ 6; it was released before the language was officially standardized and consequently allowed grossly ill-formed code to compile.

It is possible to happen, but very unlikely, IMHO. Not only MS, but other compiler vendors as well are already supporting some C++0x features and I would expect the Standard Committee to be extremly careful about breaking compatibility at this point.



回答5:

As long as you're ok with the code not being able to be compiled on an older compiler, then you have nothing to lose and might as well take advantage of the new features.



回答6:

If you expect your code to be untouched for years and want it to survive compiler changes with no intervention I would suggest you stick to C++98/03.

However most code is maintained over time so I don't think this is such an important consideration. I would recommend using what makes your code better and plan for some work when you upgrade compilers.