Prezi

Present Remotely

Send the link below via email or IM

Copy

Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in the manual

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.

DeleteCancel

Make your likes visible on Facebook?

Connect your Facebook account to Prezi and let your likes appear on your timeline.
You can change this under Settings & Account at any time.

No, thanks

KCDC '13 - Modern C++ : Language Features

No description
by Michael Price on 2 May 2013

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of KCDC '13 - Modern C++ : Language Features

Language Features Kansas City Developer Conference
May 2-4, 2013
#KCDC13

Michael Price
Senior Software Engineer
Perceptive Software

michael.b.price.dev@gmail.com
@michaelpricedev Modern C++ Performance Move Construction Utilizes r-value references

Objects "trade" state

Prevents unnecessary copies

Construction and assignment

And more! r-value References Reference to unnamed object

Or a "temporary" object

Denoted by '&&'

Examples are helpful MoveableBuffer rval_helper ()
{
return std::move(MoveableBuffer{});
}

void rval_func ()
{
// Default Construction
MoveableBuffer some_object;

// Copy Construction (always)
MoveableBuffer another_object{some_object};

// Move Construction (if available, else Copy)
MoveableBuffer yet_another_object{rval_helper()};

// Reference Capturing
MoveableBuffer & normal_ref_1 = some_object;
//MoveableBuffer && rval_ref_1 = some_object; // Error!

const MoveableBuffer & normal_ref_2 = rval_helper();
MoveableBuffer && rval_ref_2 = rval_helper();
} class MoveableBuffer
{
public:
MoveableBuffer () { buf = new char[256]; }

~MoveableBuffer () { delete[] buf; }

MoveableBuffer (const MoveableBuffer & other)
{
buf = new char[256];
std::copy(buf, buf + 256, other.buf);
}

MoveableBuffer (MoveableBuffer && other)
{
buf = other.buf;
other.buf = nullptr;
}

private:
char * buf;
}; Constant Expressions Expressions that (may) result in a compile-time constant

Formerly only available to declarations

Less computation at run-time

Denoted by 'constexpr' constexpr double circle_area (double radius)
{ return 3.14 * radius * radius; }

struct CircleArea
{
constexpr CircleArea (double radius)
: m_area(circle_area(radius)) { }

double m_area;
};

void area_computations ()
{
// Calculated at compile-time!
constexpr double a1 = circle_area(2.0);
constexpr CircleArea ca(2.5); // Compile-time ctor!

// Calculated at run-time
double r2 = 3.0;
double a2 = circle_area(r2);
} Concurrency-safe memory model thread local storage expanded plain-old-data (POD) definition Productivity Type Deduction New keywords
'auto'
'decltype'

The compiler knows the type
Refactor-proof
New function declaration syntax Range-based for loop Concise and safe syntax

Index counters no longer needed (in most cases)

Works with built-in arrays and standard containers

Extensible Lambdas Unnamed function objects

Increases code "locality"

Can be passed around, stored, and use later, even in a different thread Uniform Initialization Let there be "one way" to initialize an object!

A solution to C++'s "Most Vexing Parse" problem.

Like array-initialization Constructor Inheritance Greatly reduces typing for simple derivations of complicated classes

"All-or-nothing"

Derived class can add new constructors Constructor Delegation Allows one constructor to call another constructor for the same class

Reduces typing

Mostly removes usefulness of private "init" functions Member Field Initialization Initialize fields in class declaration

Reduces size/complexity of constructors

Reduces the chance of uninitialized fields template <typename T, typename U>
auto some_calculation (T t, U u) -> decltype(t+u)
{
return t + u;
}

void deduce_types ()
{
// 'i' is an int
auto i = 1;

// 'j' is an int
decltype(i) j = i + 1;

// 'x' is whatever 'int+int' is (an int)
auto x = some_calculation(41, 1);

// 'y' is whatever 'string+string' is (a string)
auto y = some_calculation(std::string("Hello"),
std::string("World"));
} class SomeComplicatedThing
{
public:

SomeComplicatedThing ()
: m_one(1), m_two(2.0), m_three("Three")
{ init(false); }

SomeComplicatedThing (bool make_square)
: m_one(1), m_two(2.0), m_three("Three")
{ init(make_square); }

private:

int m_one;
double m_two;
std::string m_three;

void init (bool make_square)
{ if (make_square) m_two = m_one * m_one; }
}; class SomeComplicatedThing
{
public:

SomeComplicatedThing ()
{ init(false); }

SomeComplicatedThing (bool make_square)
{ init(make_square); }

private:

int m_one = 1;
double m_two = 2.0;
std::string m_three = "Three";

void init (bool make_square)
{ if (make_square) m_two = m_one * m_one; }
}; class SomeComplicatedThing
{
public:

SomeComplicatedThing ()
: SomeComplicatedThing(false)
{ }

SomeComplicatedThing (bool make_square)
{ if (make_square) m_two = m_one * m_one; }

private:

int m_one = 1;
double m_two = 2.0;
std::string m_three = "Three";
}; class SomeDerivedThing : public SomeComplicatedThing
{
public:
using SomeComplicatedThing::SomeComplicatedThing;

void anotherMethodHere () { }
};

void ctorInheritance ()
{
SomeDerivedThing sdt;

SomeDerivedThing multiplied_sdt(true);
} Flexibility class Avenger
{
public:
Avenger () : Avenger("Newb") { }
Avenger (const char * name) { }
~Avenger () { }
Avenger (const Avenger&) { }
Avenger (Avenger &&) { }
};

Avenger getCat () { return std:move(Avenger{"Panther"}); }

void avengers_assemble ()
{
Avenger cap{"Captain America"};
Avenger irony = {"Iron-Man"};
Avenger strongest = Avenger{"Hulk"};
Avenger skrull{cap};
Avenger cat{getCat()};

//Avenger newb(); // function declaration!!!
Avenger newb{}; // variable declaration!!!

std::vector<Avenger> team = {cap, irony, strongest, cat, newb, "Thor"};
// instead of vector::push_back!
} void ranger ()
{
int some_ints[] = {0, 1, 2, 3, 4, 5};

for (auto & the_int : some_ints)
{
std::cout << ++the_int;
}

std::vector<char> cont_char = {'a', 'z'};

for (auto the_char : cont_char)
{
std::cout << the_char;
}
} template <typename TyContainer, typename TyPred>
void print_if (const TyContainer & container,
TyPred && predicate)
{
for (const auto & thing : container)
{
if (predicate(thing))
{
std::cout << thing << std::endl;
}
}
}

void printapalooza ()
{
int some_ints[5] = {0, 1, 2, 3, 4};
print_if(some_ints, [] (const int & i)
{
return i%2;
});
} template <typename T>
double sum (T && t) { return t; }

template <typename T, typename ... Args>
double sum (T && t, Args && ... args)
{ return t + sum(args...); }

template <typename T, typename ... Args>
double average (T && t, Args && ... args)
{ return sum(t, args...) / (sizeof...(args) + 1); }

void varying ()
{
cout << average(1, 2.3, 4.56, 0.789) << endl;

vector<double> v = {1, 2.3, 4.56, 0.789};
cout << average(v[0], v[1], v[2], v[3]) << endl;
} struct Distance
{
constexpr Distance (long long millimeters)
: millis(millimeters)
{ }

long long millis = 0;
};

// ignoring overflow issues...

constexpr Distance operator"" _m (unsigned long long meters)
{ return Distance(meters*1000); }

constexpr Distance operator"" _km (unsigned long long kilometers)
{ return Distance(kilometers*1000*1000); }

constexpr Distance operator"" _cm (unsigned long long centimeters)
{ return Distance(centimeters*10); }

void literal_distances ()
{
Distance a = 10_m;
Distance b = 1_km;
Distance c = 1_cm;

Distance z {1};
} template <typename T>
void some_integral_stuff (T && t)
{
static_assert(std::is_integral<T>::value,
"Template param is not an integral type");
}

struct StuffThis
{
char one;
char two;
char three;
char four;
char five; // Added in most recent build!
};

void my_stuff ()
{
some_integral_stuff(1);
some_integral_stuff(1.0); // ERROR!!!

StuffThis st;
char buffer[4];

static_assert(sizeof(StuffThis) <= sizeof(buffer),
"Uh oh, our buffer is not big enough... what changed!");

std::memcpy(buffer, &st, sizeof(st)); // Would overflow buffer!
} bool ambig (int i) { }
bool ambig (char * v) { }

void nothingness ()
{
int * _i = NULL;
int * i = nullptr;

int _j = NULL;
int j = nullptr; // ERROR!!!

if (ambig(0)) { } // ambig(int)

if (ambig(NULL)) { } // ambig(int) when NULL=0
// ambiguous when NULL=0L

if (ambig(nullptr)) { } // ambig(char*)

} Safety Strings Misc default methods deleted methods initializer list constructors extern templates template aliases unified aliasing partial template aliases local classes as template arguments User-defined Literals Decreases chance of unit mismatch errors

Leads to more expressive code Variadic Templates Allows templates to take any number of parameters

Incredibly powerful

Can also be incredibly confusing, use with care... Garbage Collection ABI GC is possible in C++, but not required

Defines some standards for GC implementations

A couple of protection methods are available inline namespaces alignas generalized attribute syntax alignof unrestricted unions nullptr Finally!

nullptr is not NULL (defined as '0' or as '(void*)0' )

Prevents unexpected overload resolution issues Static Assertions Enforces some state at compile-time

Essentially lets you define new compilation errors!

Can validate assumptions about external code override & final Provides safety for virtual functions

Clearly indicates the author's intent

Prevents unexpected function override problems scoped enumerations strongly-typed
enumerations stricter narrowing explicit conversions noexcept class Base
{
public:
virtual void l33t (double d) { }
};

class DerivedDumb : public Base
{
public:
virtual void l33t (double d) { }
};

class DerivedSmart : public Base
{
public:
virtual void l33t (double d) override { }
}; class Base
{
public:
virtual void l33tR (double d) { }
};

class DerivedDumb : public Base
{
public:
virtual void l33t (double d) { }
};

class DerivedSmart : public Base
{
public:
// This is now a compilation error!!!
virtual void l33t (double d) override { }
}; struct IMaiar
{
virtual bool shallYouPass () = 0;
};

struct GandalfGrey : public IMaiar
{
virtual bool shallYouPass () { return false; }
};

struct GandalfWhite final : public GandalfGrey
{
virtual bool shallYouPass () { return true; }
};

struct GandalfWashedOut : public GandalfWhite
{
virtual bool shallYouPass ()
{ throw "Why bother"; return false; }
}; Raw string literals Allows you to avoid lots of special character escaping in your strings

Useful for regexes, filepaths, and large static strings (XML) Unicode Strings Character types designated for popular Unicode encodings

char = UTF-8 (1 byte)
char16_t = UTF-16 (2 bytes)
char32_t = UTF-32 (4 bytes)
wchar_t = ambiguous void unicodify ()
{
const char * iso88591 = "Hello World!";
const wchar_t * platform_encoding = L"hallå världen";

// Hallo Welt
const char * utf8 = u8"\x48\x61\x6C\x6C\x6F"
u8"\x20\x57\x65\x6C\x74";

// Hello World -> Shalom Olam (but in Hebrew script)
const char16_t * utf16 = u"\u05E9\u05DC\u05D5\u05DD"
u"\u05E2\u05D5\u05DC\u05DD";

// Hello World + some SMP chars (Simplified Chinese)
const char32_t * utf32 = U"\u4F60\u597D\u4E16\u754C"
U"\U00020027\U00020929"
U"\U00021A3A\U00021F6B";

} void raw ()
{
const char * xhtml = R"(
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head/>
<body/>

</html>
)";


const char * uh_oh = R"*(
What if there is a )" in my text
)*";

} template right-angle bracket fix removal of export templates C99 features clearer SFINAE rules perfect forwarding https://github.com/michaelbprice/modern_cpp C++14 concepts 'lite' better variable capture in lambdas variable templates dynamicly-sized stack arrays generic lambdas binary literals relaxed requirements for constexpr functions function return type deduction http://isocpp.org SILVER SPONSORS GOLD SPONSORS PLATINUM SPONSORS
See the full transcript