C++ 11 features in Visual C++ 2013 Preview

July 26th, 2013 by JasonLe's Tech Leave a reply »

最近看到一篇 C++11的新特性,觉得使用以后,传参以及可变量参数会相当简便,可以学习一下

http://www.codeproject.com/Articles/623872/Cplusplus-11-features-in-Visual-Cplusplus-2013-Pre

 

中文译文:http://www.oschina.net/translate/cplusplus-11-features-in-visual-cplusplus-2013-pre

C++ 11 features in Visual C++ 2013 Preview

Introduction

When Visual C++ 2013 Preview was released in the last week of June, C++ developers were pleased to find that the compiler has added support for several ISO C++ 11 features. This article is an assemblage of those new features and includes code snippet examples that show the new features in action. You will need to download and install Visual Studio2013 Preview if you want to compile the examples in this article. I have not tested the examples on any other compiler, so I do not know how compatible it would be with GCC or Clang.

Raw string literals

VC++ 2013 now supports raw string literals. Note that it does not support Unicode string literals. A raw string literal allows you to avoid having to escape special characters which can be handy with HTML, XML, and regular expressions. Here’s an example usage.

 Collapse | Copy Code
auto s1 = R"(This is a "raw" string)";

Now s1 is a const char* containing the value – This is a “raw” string. It’s similar to the @ string literal support in C# although even that does not support embedded double quotes. So, what if you want to embed R”(…)” in a string literal. In that case, you can use the following syntax.

 Collapse | Copy Code
auto s2 = R"QQ(Example: R"(This is my raw string)")QQ";

Now s2 contains – Example: R”(This is my raw string)”. In this example, I’ve used QQ as a delimiter. This delimiter can be any string up to 16 characters in length. Raw string literals can contain newlines too.

 Collapse | Copy Code
auto s3 = R"(<tr>
<td>data</td>
</tr>)";

Eventually, whenever they add support for Unicode string literals as well, you will be able to combine them and have raw Unicode string literals.

Variadic templates

Variadic templates are templates that can take a variable number of template arguments. In my opinion, it’s more a feature for library authors than for library consumers, so I am not sure how popular its use will be among end-user C++ developers. Here’s a very simple example that shows variadic templates in action.

 Collapse | Copy Code
// Variadic template declaration
template<typename... Args> class Test;

// Specialization 1
template<typename T> class Test<T>
{
public:
  T Data;
};

// Specialization 2
template<typename T1, typename T2> class Test<T1, T2>
{
public:
  T1 Left;
  T2 Right;
};

void Foo()
{
  Test<int> data;
  data.Data = 24;

  Test<int, int> twovalues;
  twovalues.Left = 12;
  twovalues.Right = 15;
}

The intellisense kicks in and works beautifully too when using variadic templates. The implementation of variadic templates includes a sizeof... operator that returns the number of template arguments in the parameter pack.

 Collapse | Copy Code
template<typename... Args> class Test
{
public:
  size_t GetTCount()
  {
    return sizeof...(Args);
  }
};

// . . .

Test<int> data;
size_t args = data.GetTCount(); //1

Test<int, int, char*> data2;
args = data2.GetTCount(); //3

Test<int, float> data3;
args = data3.GetTCount(); //2

It’s really more of a count-of here but I guess they chose to reuse an existing operator that’s familiar to C++ developers.

A typical approach used with variadic templates is to specialize it for one argument with the rest of the arguments being optional (which works recursively). Here’s a rather naïve example which is probably an example of how not to use variadic templates, but it helped me understand variadic templates better.

 Collapse | Copy Code
template<typename... Args> class Test;

// Specialization for 0 arguments
template<> class Test<>
{
};

// Specialization for at least 1 argument

template<typename T1, typename... TRest> class Test<T1, TRest...> 
  : public Test<TRest...>
{
public:
  T1 Data;

  // This will return the base type
  Test<TRest...>& Rest() 
  {
    return *this;
  }
};

void Foo()
{
  Test<int> data;
  data.Data = 24;

  Test<int, int> twovalues;
  twovalues.Data = 10;
  // Rest() returns Test<int>
  twovalues.Rest().Data = 11;

  Test<int, int, char*> threevalues;
  threevalues.Data = 1;
  // Rest() returns Test<int, int>
  threevalues.Rest().Data = 2;
  // Rest().Rest() returns Test<char*>
  threevalues.Rest().Rest().Data = "test data";
}

Please be aware that no one ever writes code like this. This example was merely for academic purposes. There are correct ways to do this as I show in the next section.

Tuple implementation

I took a look at the std tuple header file (maintained by Stephan T. Lavavej of the VC++ team – original code by P.J. Plauger) and it would be an understatement to say that my head was spinning for a while just going through the code. To understand better how it was implemented, I simplified it down and extracted out the minimal code required to instantiate a tuple and to access its values (and be able to both read and write). It helped me understand how variadic templates are typically used with recursive expansion to significantly reduce lines of code when designing template classes.

 Collapse | Copy Code
// tuple 
template<class... _Types> class tuple;

// empty tuple
template<> class tuple<> {};

// recursive tuple definition
template<class _This,
  class... _Rest>
  class tuple<_This, _Rest...>
  : private tuple<_Rest...>
{ 
public:
  _This _Myfirst;
};

The recursive specialization uses inheritance so that we’ll end up with members for every argument type specified for the tuple. To access a tuple value, a tuple_element class is used as a sort of accessor class.

 Collapse | Copy Code
// tuple_element
template<size_t _Index, class _Tuple> struct tuple_element;

// select first element
template<class _This, class... _Rest>
struct tuple_element<0, tuple<_This, _Rest...>>
{
  typedef _This& type;
  typedef tuple<_This, _Rest...> _Ttype;
};

// recursive tuple_element definition
template <size_t _Index, class _This, class... _Rest>
struct tuple_element<_Index, tuple<_This, _Rest...>>
  : public tuple_element<_Index - 1, tuple<_Rest...> >
{ 
};

Again, recursive inheritance is used, and the 0th case is specialized as well. Notice the two typedefs, one of them is a reference to the type of the value, and the other represents the tuple with the same arguments as thetuple_element. So, given an _Index value, we can retrieve the type of the tuple and the type of the tuple value for that recursion level. This is used in the get method.

 Collapse | Copy Code
// get reference to _Index element of tuple
template<size_t _Index, class... _Types> inline
  typename tuple_element<_Index, tuple<_Types...>>::type
  get(tuple<_Types...>& _Tuple)
{
  typedef typename tuple_element<_Index, tuple<_Types...>>::_Ttype _Ttype;
  return (((_Ttype&) _Tuple)._Myfirst);
}

Notice the return type, it uses the type typedef defined above. Similarly, the tuple is cast to the _TType typedefdefined above and then we access the _Myfirst member (which represents the value). Now you can write code as follows.

 Collapse | Copy Code
tuple<int, char> t1;
get<0>(t1) = 959;
get<1>(t1) = 'A';

auto v1 = get<0>(t1);
auto v2 = get<1>(t1);

Now, this goes without saying, but I’ll say it just to be sure – but this is just for demonstration. Do not use this in production code, instead use std::tuple which does all this and lots more (there’s a reason it’s 800 lines long).

Delegating constructors

This is something C# has had for ages, so it is great to finally get it in C++ too. The compiler feature allows a type’s constructor (the delegating constructor) to have another constructor of the type in its initialization list. So when you previously had to write code like this.

 Collapse | Copy Code
class Error
{
public:
  Error()
  {
    Init(0, "Success");
  }

  Error(const char* message)
  {
    Init(-1, message);
  }

  Error(int errorCode, const char* message)
  {
    Init(errorCode, message);
  }

private:
  void Init(int errorCode, const char* message)
  {
    //...
  }
};

With delegating constructors, you can now write it as following.

 Collapse | Copy Code
class Error
{
public:
  Error() : Error(0, "Success")
  {
  }

  Error(const char* message) : Error(-1, message)
  {
  }

  Error(int errorCode, const char* message)
  {
    // ...
  }
};

Bonus reading – Here’s a humorous article written 10 years ago (May 2003) by Herb Sutter and Jim Hyslop on delegating constructors, way before the standards body started considering it as a serious proposal.

Default template arguments for function templates

This is yet another C++ 11 feature that’s now supported in VC++ 2013. Until now, the following code would not compile with VC++.

 Collapse | Copy Code
template <typename T = int> void Foo(T t = 0) { }

// error C4519: default template arguments are only 
// allowed on a class template

Visual C++ 2013 compiles this fine, and the template type is inferred correctly.

 Collapse | Copy Code
Foo(12L); // Foo<long>
Foo(12.1); // Foo<double>
Foo('A'); // Foo<char>
Foo(); // Foo<int>

The usefulness of this feature is more evident in the following example.

 Collapse | Copy Code
template <typename T> class Manager 
{
public:
  void Process(T t) { }
};

template <typename T> class AltManager
{
public:
  void Process(T t) { }
};

template <typename T, typename M = Manager<T>> void Manage(T t)
{
  M m;
  m.Process(t);
}

Manage(25); // Manage<int, Manager<int>>
Manage<int, AltManager<int>>(25); // Manage<int, AltManager<int>>

Not all arguments need to have defaults.

 Collapse | Copy Code
template <typename B, typename T = int> void Bar(B b = 0, T t = 0) { }

Bar(10); // Bar<int, int>
Bar(10L); // Bar<long, int>
Bar(10L, 20L); // Bar<long, long>
Bar(); // will not compile

When you have overloaded function templates with default arguments, you can run into compiler errors when the type cannot be inferred.

 Collapse | Copy Code
template <typename T = int> void Foo(T t = 0) { }
template <typename B, typename T = int> void Foo(B b = 0, T t = 0) { }

Foo(12L); // will not compile
Foo(12.1); // will not compile
Foo('A'); // will not compile
Foo(); // Foo<int>

So, that’s one thing to watch out for when using default template arguments with function templates.

Explicit conversion operators

I remember a rather embarrassing day in August 2004 when I realized that despite considering myself to be a decent C++ programmer, I had not until then known about the explicit keyword. I have a blog entry from back then.

Just to summarize the use of explicit, consider the example below.

 Collapse | Copy Code
class Test1
{
public:
  explicit Test1(int) { }
};

void Foo()
{
  Test1 t1(20);
  Test1 t2 = 20; // will not compile
}

While this could be done with conversion constructors, there was no way to do this for conversion operators because the standard did not support it. The bad thing about this was that you could not design a class to have consistency between conversion constructors and conversion operators. Consider the example below.

 Collapse | Copy Code
class Test1
{
public:
  explicit Test1(int) { }
};

class Test2
{
  int x;
public:
  Test2(int i) : x(i) { }
  operator Test1() { return Test1(x); }
};

void Foo()
{
  Test2 t1 = 20;
  Test1 t2 = t1; // will compile
}

That compiles now. Well, with C++ 11, you can now apply explicit on your conversion operators too.

 Collapse | Copy Code
class Test2
{
  int x;
public:
  Test2(int i) : x(i) { }
  explicit operator Test1() { return Test1(x); }
};

void Foo()
{
  Test2 t1 = 20;
  Test1 t2 = (Test1)t1; // this compiles
  Test1 t3 = t1; // will not compile
}

Here’s a not so obvious behavior with bool conversion operators.

 Collapse | Copy Code
class Test3
{
public:
  operator bool() { return true; }
};

void Foo()
{
  Test3 t3;
  if (t3)
  {
  }

  bool b = t3;
}

That compiles fine. Now try adding explicit to the operator.

 Collapse | Copy Code
class Test3
{
public:
  explicit operator bool() { return true; }
};

void Foo()
{
  Test3 t3;
  if (t3) // this compiles!
  {
  }

  bool b = t3; // will not compile
}

As expected, the 2nd conversion failed to compile, but the first one did. That’s because the if construct’s boolconversion is treated as explicit. So you need to be wary of this, just adding explicit to your bool conversion operator will not keep your type safe from accidental conversions to bool.

Initializer lists and uniform initialization

We’ve always been able to use initializer lists with arrays, now you can do it with any type that has a method that takes an argument of type std::initializer_list<T> (including constructors). The standard library collections have all been updated to support initializer lists.

 Collapse | Copy Code
void foo()
{
  vector<int> vecint = { 3, 5, 19, 2 };
  map<int, double> mapintdoub =
  {
    { 4, 2.3},
    { 12, 4.1 },
    { 6, 0.7 }
  };
}

And it’s trivial to do this with your own functions.

 Collapse | Copy Code
void bar1(const initializer_list<int>& nums) 
{
  for (auto i : nums)
  {
    // use i
  }
}

bar1({ 1, 4, 6 });

You can also do it with your user defined types.

 Collapse | Copy Code
class bar2
{
public:
  bar2(initializer_list<int> nums) { }
};

class bar3
{
public:
  bar3(initializer_list<bar2> items) { }
};

bar2 b2 = { 3, 7, 88 };

bar3 b3 = { {1, 2}, { 14 }, { 11, 8 } };

Uniform initialization is a related feature that’s been added to C++ 11. It automatically uses the matching constructor.

 Collapse | Copy Code
class bar4
{
  int x;
  double y;
  string z;

public:
  bar4(int, double, string) { }
};

class bar5
{
public:
  bar5(int, bar4) { }
};

bar4 b4 { 12, 14.3, "apples" };

bar5 b5 { 10, { 1, 2.1, "bananas" } };

If there’s an initializer-list constructor, it takes precedence over another matching constructor.

 Collapse | Copy Code
class bar6
{
public:
  bar6(int, int) // (1)
  {
    // ...
  }

  bar6(initializer_list<int>) // (2)
  {
    // ...
  }
};

bar6 b6 { 10, 10 }; // --> calls (2) above

Alright, that’s it. As usual, feedback and criticism are very welcome. Thank you
.