SlideShare a Scribd company logo
Andrey Upadyshev
Hot C++:

Universal References &
Perfect Forwarding
Licensed under a CC BY-SA 4.0 License. Version of 2017.11.16
1
Imagine a simple factory:
template<typename T, typename ???>

shared_ptr<T> makeShared(??? arg)

{

return shared_ptr<T>(new T(arg));

}
❖ The intent here is to pass the argument arg from the factory
function to T's constructor.
❖ Ideally, everything should behave just as if the factory function
weren't there and the constructor were called directly in the
client code i.e. a perfect forwarding.
Perfect Forwarding: The Problem
2
C++98 Solution
First approach is to take arg by const ref:
template<typename T, typename Arg>

shared_ptr<T> makeShared(const Arg& arg) {

return shared_ptr<T>(new T(arg));

}
std::string readFile();

makeShared<Foo>(readFile());

makeShared<Bar>(42);
Connection conn;

makeShared<Client>(conn);

// Compilation error: non-const lvalue ref passed
Overload for non-const ref should be added:
template<typename T, typename Arg> 

shared_ptr<T> makeShared(Arg& arg) {

return shared_ptr<T>(new T(arg));

}
3
C++98 Solution
template<typename T, typename Arg>

shared_ptr<T> makeShared(const Arg& arg);



template<typename T, typename Arg>

shared_ptr<T> makeShared(Arg& arg);
Drawbacks:
❖ 2 overloads for one argument, 2^N overloads for N
arguments.
❖ Move semantics blocked in C++11.

- No more overloads, please!
4
Perfect Forwarding
Good news for everybody:

C++11 finally got a perfect solution!
But wait a bit…
5
Reference-Collapsing Rules
C++11 got new reference-collapsing rules in template instantiation context:
template<class T>

struct Collapse {

typedef T&& RvRef;

typedef T& LvRef;

}; typename Collapse<X&>::RvRef
• An rvalue reference to an rvalue reference becomes (collapses into) an
rvalue reference:

Collapse<X&&>::RvRef (X&& &&) → X&&
• Any other reference to reference (i.e., all combinations involving an
lvalue reference) collapses into an lvalue reference:

Collapse<X&&>::LvRef (X&& &) → X& 

Collapse<X&>::RvRef (X& &&) → X&

Collapse<X&>::LvRef (X& &) → X&
❖ Reference-collapsing preserves cv-qualifiers of original type.
❖ It is still impossible to explicitly declare reference to reference.
6
Template Argument Deduction Rule
C++11 got special template argument deduction rule for
function templates:
template<typename T>

void foo(T&& t);
• When called with lvalue of type X then

T resolves to X& → argument type collapses into X&
• When called with rvalue of type X then

T resolves to X → argument type becomes X&&
7
Universal References
If a variable or parameter is declared to have type T&& for some
deduced type T, that variable or parameter is a universal reference.
— Scott Meyers, Universal References in C++11
template<typename T>

void foo(T&& t); // t is a universal reference
Of course, the name of typename does not matter,

it can be any type&&.
They are also known as forwarding references.
8
Universal References: Examples
template<typename Arg> // [1.1]

void foo(Arg&& arg);
arg is universal reference
void bar(Bar&& op); // [1.2]

std::string&& s = …; // [1.3]
Fully specified type ⇒ no type deduction, op and s are rvalue references
template<typename Arg> // [1.4]

void foo(const Arg&& arg);
Should be exactly type&& were type is deduced ⇒ arg is const rvalue
reference
template<typename Arg> // [1.5]

void foo(Arg& arg);
Should be type&& ⇒ arg is lvalue reference
9
Universal References: Examples
template<typename T>

class Vector {

Vector(Vector&& rhs); // [2.1]

…

void push_back(T&& t); // [2.2]

};
Fully specified type (When function is called the template is already
instantiated so Vector and T are “fixed”) ⇒ no type deduction, rhs and t
are rvalue references
template<typename T>

class Vector {

template<typename U> // [2.3]

Vector(U&& rhs);

…

};
rhs is universal reference
10
Universal References: Examples
template<typename T> // [3.1]

void print(std::vector<T>&& arg);
Should be exactly type&& were type is deduced ⇒ arg is rvalue
reference
template<typename... Args> // [3.2]

void foo(Args&&... args);
Parameter pack of universal references
auto&& i = …; // [3.3]
It is exactly type&& where type is deduced ⇒ i is universal reference
[](auto&& arg) {…}; // [3.4] C++14 lambda
It is exactly type&& where type is deduced ⇒ arg is universal
reference
11
std::forward
template<typename T>

void foo(T&& t) {

bar(std::forward<T>(t)));

}
❖ Forwards the argument to another function with preserving the
type, cv-qualifiers and value category (lvalue/rvalue).
❖ Somehow similar to std::move but should be applied only to
universal references
❖ std::forward is a conditional cast to rvalue (while std::move is
an unconditional one):
❖ Rvalue if applied to rvalue reference
❖ Lvalue if applied to lvalue reference
❖ Both do nothing at runtime
12
Perfect Forwarding: Solved!
Universal references and std::forward are a key:
template<typename T, typename Arg>

shared_ptr<T> makeShared(Arg&& arg)

{

return shared_ptr<T>(

new T(std::forward<Arg>(arg)));

}
❖ No overloads needed
❖ Forwarded arguments are exactly the same that was passed by
the caller.
❖ No copies or moves performed
13
Plays Nice With Variadic Templates
Perfectly forwards any number of arguments:
template<typename T, typename... Args>
shared_ptr<T> makeShared(Args&&... args)
{
return shared_ptr<T>(
new T(std::forward<Args>(args)...));
}
14
15
Don’t Confuse std::move With std::forward
❖ std::move is used to unconditionally cast rvalue reference (or something
need to be forced) to rvalue.
template<typename T, typename Arg>

shared_ptr<T> makeShared(Arg&& arg)

{

return shared_ptr<T>(

new T(std::move(arg))); // What is wrong?

}
Using std::move with universal reference may lead to unexpected
move from lvalue.
❖ std::forward is used to forward universal reference, i.e. to conditionally
cast one to rvalue. Using it with rvalue reference is excessively uncommon
and so confusing.
16
URefs And std::forward Go Together
A universal reference is [almost] always used in
combination with std::forward. If you see former
without latter or vice versa, look for error!
Remember its second name a forwarding reference.
17
template<typename T>

void logAndBar(T&& t) {

std::cout << t << ‘n’;

bar(std::forward<T>(t)));

}

template<typename T>

Foo makeFoo(T&& t) {

return std::forward<T>(t);

}
template<class T>

struct Wrapper {

…

template<class U>

Wrapper(int id, U&& v)

: m_id(id) 

, m_val(std::forward<U>(v))

{}

};



Use URefs And std::forward Carefully
❖ template<class T>

void foo(T&& t) {

Bar b(std::forward<T>(t));

std::cout << t.value(); // What is wrong?

…

}
Do not use forwarded-away objects because they may be in moved-
from state.
❖ Remember that std::forward may act as std::move. Check
previous presentation for std::move and rvalue related concerns.
❖ Remember that universal reference may be either rvalue reference
or lvalue reference. Write code accordingly.
18
Avoid Overloading on URefs
Imagine that we want to differently process rvalues (first overload)
and lvalues (second one):
template<typename T>

void foo(T&& t) {… std::move(t); …} // [1] rvalues
template<typename T>

void foo(T const& t) {…} // [2] lvalues
std::string s = “wow”;

foo(s);
WTF, overload [1] is called! Only const lvalues go to [2], all the rest
including non-const lvalues go to [1] because it takes universal
reference ⇒ accepts everything ⇒ a better match for everything
except const lvalue ref.
19
Avoid Overloading on URefs
Imagine that we want to have overload for integers:
template<typename T>

void foo(T&& t) {…} // [1] general case
void foo(long t) {…} // [2] integers
short s = 42;

foo(s);
WTF, overload [1] is called! Only longs go to [2], all the rest
including integers that need to be promoted to long integer go to
[1] because it takes universal reference ⇒ accepts everything ⇒
a better match for everything except a long integer.
20
Avoid Overloading on URefs
❖ Problem’s root cause is that universal reference parameter is too
“greedy” (by purpose) so become a better match more frequently
than expected.
❖ There are some solutions (Partially stolen from Meyers’ book):
❖ Abandon overloading by using different function names or
different number of parameters.
❖ Pass by const reference instead of universal reference.
❖ Pass params that are movable and copyable by value (and get
rid of template that uses universal references at all)
❖ Tag dispatch
❖ Constrain template that uses universal references
21
Avoid Overloading on URefs: Tag Dispatch
Using of compile time dispatching to implement overloading for
rvalues and lvalues:
template<typename T>

void foo(T&& t)

{

foo_impl(std::forward<T>(t),

std::is_lvalue_reference<T>());

}
template<typename T>

void foo_impl(T&& t, std::true_type) {…} // lvalues
template<typename T>

void foo_impl(T&& t, std::false_type) {…} // rvalues
22
URefs And Copy Constructor
Consider the simple wrapper:
template<typename T>

struct Wrapper {

T m_value;

…

template<typename U> // Single arg for simplicity

explicit Wrapper(U&& u)

: m_value(std::forward<U>(u)) {}

};
The purpose is to allow to construct Wrapper with whatever wrapped
type constructor accepts:
Wrapper<std::string> hello_world(“Hello, World!”);
23
URefs And Copy Constructor
template<typename T>

struct Wrapper {

T m_value;

…

template<typename U>

explicit Wrapper(U&& u)

: m_value(std::forward<U>(u)) {}

};
Looks OK?
Wrapper<std::string> w1(“Hello, World!”);

Wrapper<std::string> w2(w1); // Compilation error
For non-const lvalue reference the forwarding constructor is a better
match than [generated] copy constructor:
Wrapper(const Wrapper& rhs);
24
URefs And Copy Constructor
❖ Copy assignment operator has the same issue.
❖ Variadic forwarding constructor has the same issue.
template<typename... Ts>

struct tuple

{

template<typename... Us>

explicit tuple(Us&&... us);

// May be chosen instead of copy constructor

…

};
25
Constraining URef Template
Possible solution is to disable forwarding constructor for Wrapper and derived types:
template<typename T>

struct Wrapper {

T m_value;

…

template<

typename U,

typename = disable_if_same_or_derived_t<Wrapper, U>>

explicit Wrapper(U&& u)

: m_value(std::forward<U>(u)) {}

};
template<typename Base, typename Derived>

using disable_if_same_or_derived_t =

std::enable_if_t<

!std::is_base_of<

Base,

std::decay_t<Derived>

>::value

>; // C++14. A bit more verbose in C++11
26
std::enable_if
metafunction is a convenient
way to leverage SFINAE to
conditionally remove functions
from overload resolution based
on type traits.
Constraining URef Template 2
Another solution is to enable forwarding constructor only for types that may be used to construct T:
template<typename T>

struct Wrapper {

T m_value;

…

template<

typename U,

typename = std::enable_if_t<std::is_constructible<T, U&&>::value>>

explicit Wrapper(U&& u)

: m_value(std::forward<U>(u)) {}

}; // C++14. A bit more verbose in C++11
Easily extended to any number of arguments:
template<typename T>

struct Wrapper {

T m_value;

…

template<

typename... U,

typename = std::enable_if_t<std::is_constructible<T, U&&...>::value>>

explicit Wrapper(U&&... u)

: m_value(std::forward<U>(u)...) {}

}; // C++14. A bit more verbose in C++11
27
Constraining URef Template 3
Another solution is to disable forwarding constructor for types that otherwise
convertible to Wrapper. Which is true for Wrapper and derived types, for types that
got a dedicated constructor and types that implement a conversion to Wrapper.
template<class T>

struct Wrapper {

T m_value;

…

template<

typename U,

typename = std::enable_if_t<!std::is_convertible<U&&, Wrapper>::value>>

explicit Wrapper(U&& u);

explicit Wrapper(const Bar& bar); // A dedicated constructor for Bar 

};
template<class T>
struct Foo {
operator Wrapper<T> () const; // Foo<T> provides a conversion to Wrapper<T>
};
Bar bar;
Foo<std::string> foo;
Wrapper<std::string> w1(bar), w2(foo); // ^ C++14. A bit more verbose in C++11
28
Perfect Forwarding Failures
❖ Braced initializer. Compiler can not deduce the type.

makeShared<std::vector<int>>({1, 2, 3});

User has to explicitly specify a type:

makeShared<std::vector<int>>(

std::initialized_list<int>({1, 2, 3}));

or

auto list = {1, 2, 3};

makeShared<std::vector<int>>(list);
❖ Overloaded function and function template names. A set of
functions that compiler can not choose a right one from.

You have to explicitly choose one function by casting the function
to a specific function pointer type.
29
Perfect Forwarding Failures
❖ 0 or NULL as null pointers. They are deduced to integral type instead of
pointer type. Use nullptr instead (not only in this case but always!).
❖ Declaration-only static const and constexpr data. Causes linker error.
struct Calendar {

static const int numberOfMonths = 12;

…

};
makeShared<int>(Calendar::numberOfMonths);
User has to add a definition for the data or pass a copy:
makeShared<int>(int(Calendar::numberOfMonths));
❖ Non-const bit-field. Non-const reference cannot bind to a bit-field. User has
to pass a copy:
makeShared<int>(int(var.bitField));
30
Useful Links
Thomas Becker, Perfect Forwarding: The Problem

http://thbecker.net/articles/rvalue_references/section_07.html
Scott Meyers, Universal References

http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers
Eric Niebler, Universal References and the Copy Constructor

http://ericniebler.com/2013/08/07/universal-references-and-the-copy-constructo/
(Im)perfect forwarding with variadic templates

stackoverflow.com/questions/13296461/imperfect-forwarding-with-variadic-
templates
C++11 Standard (final plus minor editorial changes)
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
Scott Meyers, Effective Modern C++, (Item 1 & chapter 4)
31
Questions?
32

More Related Content

What's hot

JDKの選択肢とサーバーサイドでの選び方
JDKの選択肢とサーバーサイドでの選び方JDKの選択肢とサーバーサイドでの選び方
JDKの選択肢とサーバーサイドでの選び方
Takahiro YAMADA
 
エキスパートGo
エキスパートGoエキスパートGo
エキスパートGo
Takuya Ueda
 
これからのJDK 何を選ぶ?どう選ぶ? (v1.2) in 熊本
これからのJDK 何を選ぶ?どう選ぶ? (v1.2) in 熊本これからのJDK 何を選ぶ?どう選ぶ? (v1.2) in 熊本
これからのJDK 何を選ぶ?どう選ぶ? (v1.2) in 熊本
Takahiro YAMADA
 
Working Remotely (via SSH) Rocks!
Working Remotely (via SSH) Rocks!Working Remotely (via SSH) Rocks!
Working Remotely (via SSH) Rocks!
Kent Chen
 
Deep C
Deep CDeep C
Deep C
Olve Maudal
 
Q2.12: Debugging with GDB
Q2.12: Debugging with GDBQ2.12: Debugging with GDB
Q2.12: Debugging with GDB
Linaro
 
jq: JSON - Like a Boss
jq: JSON - Like a Bossjq: JSON - Like a Boss
jq: JSON - Like a Boss
Bob Tiernay
 
If-else and switch-case
If-else and switch-caseIf-else and switch-case
If-else and switch-case
Manash Kumar Mondal
 
Go入門
Go入門Go入門
Go入門
Takuya Ueda
 
コンポーネントの分割に関する考察
コンポーネントの分割に関する考察コンポーネントの分割に関する考察
コンポーネントの分割に関する考察
Yahoo!デベロッパーネットワーク
 
トランザクションスクリプトのすすめ
トランザクションスクリプトのすすめトランザクションスクリプトのすすめ
トランザクションスクリプトのすすめ
pospome
 
C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会Akihiko Matuura
 
C++11: Rvalue References, Move Semantics, Perfect Forwarding
C++11: Rvalue References, Move Semantics, Perfect ForwardingC++11: Rvalue References, Move Semantics, Perfect Forwarding
C++11: Rvalue References, Move Semantics, Perfect Forwarding
Francesco Casalegno
 
TLS, HTTP/2演習
TLS, HTTP/2演習TLS, HTTP/2演習
TLS, HTTP/2演習
shigeki_ohtsu
 
Effective Modern C++ 勉強会#3 Item16
Effective Modern C++ 勉強会#3 Item16Effective Modern C++ 勉強会#3 Item16
Effective Modern C++ 勉強会#3 Item16
Mitsuru Kariya
 
Overview of c language
Overview of c languageOverview of c language
Overview of c languageshalini392
 
Javaバイトコード入門
Javaバイトコード入門Javaバイトコード入門
Javaバイトコード入門
Kota Mizushima
 
Completable future
Completable futureCompletable future
Completable future
Srinivasan Raghvan
 
BuildKitの概要と最近の機能
BuildKitの概要と最近の機能BuildKitの概要と最近の機能
BuildKitの概要と最近の機能
Kohei Tokunaga
 
オススメの標準・準標準パッケージ20選
オススメの標準・準標準パッケージ20選オススメの標準・準標準パッケージ20選
オススメの標準・準標準パッケージ20選
Takuya Ueda
 

What's hot (20)

JDKの選択肢とサーバーサイドでの選び方
JDKの選択肢とサーバーサイドでの選び方JDKの選択肢とサーバーサイドでの選び方
JDKの選択肢とサーバーサイドでの選び方
 
エキスパートGo
エキスパートGoエキスパートGo
エキスパートGo
 
これからのJDK 何を選ぶ?どう選ぶ? (v1.2) in 熊本
これからのJDK 何を選ぶ?どう選ぶ? (v1.2) in 熊本これからのJDK 何を選ぶ?どう選ぶ? (v1.2) in 熊本
これからのJDK 何を選ぶ?どう選ぶ? (v1.2) in 熊本
 
Working Remotely (via SSH) Rocks!
Working Remotely (via SSH) Rocks!Working Remotely (via SSH) Rocks!
Working Remotely (via SSH) Rocks!
 
Deep C
Deep CDeep C
Deep C
 
Q2.12: Debugging with GDB
Q2.12: Debugging with GDBQ2.12: Debugging with GDB
Q2.12: Debugging with GDB
 
jq: JSON - Like a Boss
jq: JSON - Like a Bossjq: JSON - Like a Boss
jq: JSON - Like a Boss
 
If-else and switch-case
If-else and switch-caseIf-else and switch-case
If-else and switch-case
 
Go入門
Go入門Go入門
Go入門
 
コンポーネントの分割に関する考察
コンポーネントの分割に関する考察コンポーネントの分割に関する考察
コンポーネントの分割に関する考察
 
トランザクションスクリプトのすすめ
トランザクションスクリプトのすすめトランザクションスクリプトのすすめ
トランザクションスクリプトのすすめ
 
C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会
 
C++11: Rvalue References, Move Semantics, Perfect Forwarding
C++11: Rvalue References, Move Semantics, Perfect ForwardingC++11: Rvalue References, Move Semantics, Perfect Forwarding
C++11: Rvalue References, Move Semantics, Perfect Forwarding
 
TLS, HTTP/2演習
TLS, HTTP/2演習TLS, HTTP/2演習
TLS, HTTP/2演習
 
Effective Modern C++ 勉強会#3 Item16
Effective Modern C++ 勉強会#3 Item16Effective Modern C++ 勉強会#3 Item16
Effective Modern C++ 勉強会#3 Item16
 
Overview of c language
Overview of c languageOverview of c language
Overview of c language
 
Javaバイトコード入門
Javaバイトコード入門Javaバイトコード入門
Javaバイトコード入門
 
Completable future
Completable futureCompletable future
Completable future
 
BuildKitの概要と最近の機能
BuildKitの概要と最近の機能BuildKitの概要と最近の機能
BuildKitの概要と最近の機能
 
オススメの標準・準標準パッケージ20選
オススメの標準・準標準パッケージ20選オススメの標準・準標準パッケージ20選
オススメの標準・準標準パッケージ20選
 

Similar to Hot С++: Universal References And Perfect Forwarding

C++ references
C++ referencesC++ references
C++ references
corehard_by
 
C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0
Yaser Zhian
 
Summary of effective modern c++ item1 2
Summary of effective modern c++ item1 2Summary of effective modern c++ item1 2
Summary of effective modern c++ item1 2
Young Ha Kim
 
Effective Modern C++
Effective Modern C++Effective Modern C++
Effective Modern C++
Wang Hsiangkai
 
The Future of C++
The Future of C++The Future of C++
The Future of C++
Sasha Goldshtein
 
Templates presentation
Templates presentationTemplates presentation
Templates presentation
malaybpramanik
 
Templates2
Templates2Templates2
Templates2
zindadili
 
COM1407: Type Casting, Command Line Arguments and Defining Constants
COM1407: Type Casting, Command Line Arguments and Defining Constants COM1407: Type Casting, Command Line Arguments and Defining Constants
COM1407: Type Casting, Command Line Arguments and Defining Constants
Hemantha Kulathilake
 
Effective Modern C++ 勉強会#7 Item 27
Effective Modern C++ 勉強会#7 Item 27Effective Modern C++ 勉強会#7 Item 27
Effective Modern C++ 勉強会#7 Item 27
Mitsuru Kariya
 
OpenGurukul : Language : C Programming
OpenGurukul : Language : C ProgrammingOpenGurukul : Language : C Programming
OpenGurukul : Language : C Programming
Open Gurukul
 
[GRCPP] Introduction to concepts (C++20)
[GRCPP] Introduction to concepts (C++20)[GRCPP] Introduction to concepts (C++20)
[GRCPP] Introduction to concepts (C++20)
Dimitrios Platis
 
C intro
C introC intro
C intro
Kamran
 
Please code in C++ and do only the �TO DO�s and all of them. There a.pdf
Please code in C++ and do only the �TO DO�s and all of them. There a.pdfPlease code in C++ and do only the �TO DO�s and all of them. There a.pdf
Please code in C++ and do only the �TO DO�s and all of them. There a.pdf
farankureshi
 
ANSI C REFERENCE CARD
ANSI C REFERENCE CARDANSI C REFERENCE CARD
ANSI C REFERENCE CARD
Tia Ricci
 
12 computer science_notes_ch01_overview_of_cpp
12 computer science_notes_ch01_overview_of_cpp12 computer science_notes_ch01_overview_of_cpp
12 computer science_notes_ch01_overview_of_cpp
sharvivek
 
Cat's anatomy
Cat's anatomyCat's anatomy
Cat's anatomy
Nicola Bonelli
 
Programming C Part 03
Programming C Part 03Programming C Part 03
Programming C Part 03
Raselmondalmehedi
 

Similar to Hot С++: Universal References And Perfect Forwarding (20)

C++ references
C++ referencesC++ references
C++ references
 
C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0
 
Summary of effective modern c++ item1 2
Summary of effective modern c++ item1 2Summary of effective modern c++ item1 2
Summary of effective modern c++ item1 2
 
Effective Modern C++
Effective Modern C++Effective Modern C++
Effective Modern C++
 
The Future of C++
The Future of C++The Future of C++
The Future of C++
 
Savitch Ch 17
Savitch Ch 17Savitch Ch 17
Savitch Ch 17
 
Templates presentation
Templates presentationTemplates presentation
Templates presentation
 
Templates2
Templates2Templates2
Templates2
 
COM1407: Type Casting, Command Line Arguments and Defining Constants
COM1407: Type Casting, Command Line Arguments and Defining Constants COM1407: Type Casting, Command Line Arguments and Defining Constants
COM1407: Type Casting, Command Line Arguments and Defining Constants
 
Effective Modern C++ 勉強会#7 Item 27
Effective Modern C++ 勉強会#7 Item 27Effective Modern C++ 勉強会#7 Item 27
Effective Modern C++ 勉強会#7 Item 27
 
OpenGurukul : Language : C Programming
OpenGurukul : Language : C ProgrammingOpenGurukul : Language : C Programming
OpenGurukul : Language : C Programming
 
Ch02
Ch02Ch02
Ch02
 
Savitch ch 17
Savitch ch 17Savitch ch 17
Savitch ch 17
 
[GRCPP] Introduction to concepts (C++20)
[GRCPP] Introduction to concepts (C++20)[GRCPP] Introduction to concepts (C++20)
[GRCPP] Introduction to concepts (C++20)
 
C intro
C introC intro
C intro
 
Please code in C++ and do only the �TO DO�s and all of them. There a.pdf
Please code in C++ and do only the �TO DO�s and all of them. There a.pdfPlease code in C++ and do only the �TO DO�s and all of them. There a.pdf
Please code in C++ and do only the �TO DO�s and all of them. There a.pdf
 
ANSI C REFERENCE CARD
ANSI C REFERENCE CARDANSI C REFERENCE CARD
ANSI C REFERENCE CARD
 
12 computer science_notes_ch01_overview_of_cpp
12 computer science_notes_ch01_overview_of_cpp12 computer science_notes_ch01_overview_of_cpp
12 computer science_notes_ch01_overview_of_cpp
 
Cat's anatomy
Cat's anatomyCat's anatomy
Cat's anatomy
 
Programming C Part 03
Programming C Part 03Programming C Part 03
Programming C Part 03
 

Recently uploaded

GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
Neo4j
 
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
Aftab Hussain
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
Łukasz Chruściel
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
Google
 
Pro Unity Game Development with C-sharp Book
Pro Unity Game Development with C-sharp BookPro Unity Game Development with C-sharp Book
Pro Unity Game Development with C-sharp Book
abdulrafaychaudhry
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
Globus
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptxText-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
ShamsuddeenMuhammadA
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Globus
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
Globus
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
Globus
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
Donna Lenk
 

Recently uploaded (20)

GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
 
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
 
Pro Unity Game Development with C-sharp Book
Pro Unity Game Development with C-sharp BookPro Unity Game Development with C-sharp Book
Pro Unity Game Development with C-sharp Book
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptxText-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
 

Hot С++: Universal References And Perfect Forwarding

  • 1. Andrey Upadyshev Hot C++:
 Universal References & Perfect Forwarding Licensed under a CC BY-SA 4.0 License. Version of 2017.11.16 1
  • 2. Imagine a simple factory: template<typename T, typename ???>
 shared_ptr<T> makeShared(??? arg)
 {
 return shared_ptr<T>(new T(arg));
 } ❖ The intent here is to pass the argument arg from the factory function to T's constructor. ❖ Ideally, everything should behave just as if the factory function weren't there and the constructor were called directly in the client code i.e. a perfect forwarding. Perfect Forwarding: The Problem 2
  • 3. C++98 Solution First approach is to take arg by const ref: template<typename T, typename Arg>
 shared_ptr<T> makeShared(const Arg& arg) {
 return shared_ptr<T>(new T(arg));
 } std::string readFile();
 makeShared<Foo>(readFile());
 makeShared<Bar>(42); Connection conn;
 makeShared<Client>(conn);
 // Compilation error: non-const lvalue ref passed Overload for non-const ref should be added: template<typename T, typename Arg> 
 shared_ptr<T> makeShared(Arg& arg) {
 return shared_ptr<T>(new T(arg));
 } 3
  • 4. C++98 Solution template<typename T, typename Arg>
 shared_ptr<T> makeShared(const Arg& arg);
 
 template<typename T, typename Arg>
 shared_ptr<T> makeShared(Arg& arg); Drawbacks: ❖ 2 overloads for one argument, 2^N overloads for N arguments. ❖ Move semantics blocked in C++11.
 - No more overloads, please! 4
  • 5. Perfect Forwarding Good news for everybody:
 C++11 finally got a perfect solution! But wait a bit… 5
  • 6. Reference-Collapsing Rules C++11 got new reference-collapsing rules in template instantiation context: template<class T>
 struct Collapse {
 typedef T&& RvRef;
 typedef T& LvRef;
 }; typename Collapse<X&>::RvRef • An rvalue reference to an rvalue reference becomes (collapses into) an rvalue reference:
 Collapse<X&&>::RvRef (X&& &&) → X&& • Any other reference to reference (i.e., all combinations involving an lvalue reference) collapses into an lvalue reference:
 Collapse<X&&>::LvRef (X&& &) → X& 
 Collapse<X&>::RvRef (X& &&) → X&
 Collapse<X&>::LvRef (X& &) → X& ❖ Reference-collapsing preserves cv-qualifiers of original type. ❖ It is still impossible to explicitly declare reference to reference. 6
  • 7. Template Argument Deduction Rule C++11 got special template argument deduction rule for function templates: template<typename T>
 void foo(T&& t); • When called with lvalue of type X then
 T resolves to X& → argument type collapses into X& • When called with rvalue of type X then
 T resolves to X → argument type becomes X&& 7
  • 8. Universal References If a variable or parameter is declared to have type T&& for some deduced type T, that variable or parameter is a universal reference. — Scott Meyers, Universal References in C++11 template<typename T>
 void foo(T&& t); // t is a universal reference Of course, the name of typename does not matter,
 it can be any type&&. They are also known as forwarding references. 8
  • 9. Universal References: Examples template<typename Arg> // [1.1]
 void foo(Arg&& arg); arg is universal reference void bar(Bar&& op); // [1.2]
 std::string&& s = …; // [1.3] Fully specified type ⇒ no type deduction, op and s are rvalue references template<typename Arg> // [1.4]
 void foo(const Arg&& arg); Should be exactly type&& were type is deduced ⇒ arg is const rvalue reference template<typename Arg> // [1.5]
 void foo(Arg& arg); Should be type&& ⇒ arg is lvalue reference 9
  • 10. Universal References: Examples template<typename T>
 class Vector {
 Vector(Vector&& rhs); // [2.1]
 …
 void push_back(T&& t); // [2.2]
 }; Fully specified type (When function is called the template is already instantiated so Vector and T are “fixed”) ⇒ no type deduction, rhs and t are rvalue references template<typename T>
 class Vector {
 template<typename U> // [2.3]
 Vector(U&& rhs);
 …
 }; rhs is universal reference 10
  • 11. Universal References: Examples template<typename T> // [3.1]
 void print(std::vector<T>&& arg); Should be exactly type&& were type is deduced ⇒ arg is rvalue reference template<typename... Args> // [3.2]
 void foo(Args&&... args); Parameter pack of universal references auto&& i = …; // [3.3] It is exactly type&& where type is deduced ⇒ i is universal reference [](auto&& arg) {…}; // [3.4] C++14 lambda It is exactly type&& where type is deduced ⇒ arg is universal reference 11
  • 12. std::forward template<typename T>
 void foo(T&& t) {
 bar(std::forward<T>(t)));
 } ❖ Forwards the argument to another function with preserving the type, cv-qualifiers and value category (lvalue/rvalue). ❖ Somehow similar to std::move but should be applied only to universal references ❖ std::forward is a conditional cast to rvalue (while std::move is an unconditional one): ❖ Rvalue if applied to rvalue reference ❖ Lvalue if applied to lvalue reference ❖ Both do nothing at runtime 12
  • 13. Perfect Forwarding: Solved! Universal references and std::forward are a key: template<typename T, typename Arg>
 shared_ptr<T> makeShared(Arg&& arg)
 {
 return shared_ptr<T>(
 new T(std::forward<Arg>(arg)));
 } ❖ No overloads needed ❖ Forwarded arguments are exactly the same that was passed by the caller. ❖ No copies or moves performed 13
  • 14. Plays Nice With Variadic Templates Perfectly forwards any number of arguments: template<typename T, typename... Args> shared_ptr<T> makeShared(Args&&... args) { return shared_ptr<T>( new T(std::forward<Args>(args)...)); } 14
  • 15. 15
  • 16. Don’t Confuse std::move With std::forward ❖ std::move is used to unconditionally cast rvalue reference (or something need to be forced) to rvalue. template<typename T, typename Arg>
 shared_ptr<T> makeShared(Arg&& arg)
 {
 return shared_ptr<T>(
 new T(std::move(arg))); // What is wrong?
 } Using std::move with universal reference may lead to unexpected move from lvalue. ❖ std::forward is used to forward universal reference, i.e. to conditionally cast one to rvalue. Using it with rvalue reference is excessively uncommon and so confusing. 16
  • 17. URefs And std::forward Go Together A universal reference is [almost] always used in combination with std::forward. If you see former without latter or vice versa, look for error! Remember its second name a forwarding reference. 17 template<typename T>
 void logAndBar(T&& t) {
 std::cout << t << ‘n’;
 bar(std::forward<T>(t)));
 }
 template<typename T>
 Foo makeFoo(T&& t) {
 return std::forward<T>(t);
 } template<class T>
 struct Wrapper {
 …
 template<class U>
 Wrapper(int id, U&& v)
 : m_id(id) 
 , m_val(std::forward<U>(v))
 {}
 };
 

  • 18. Use URefs And std::forward Carefully ❖ template<class T>
 void foo(T&& t) {
 Bar b(std::forward<T>(t));
 std::cout << t.value(); // What is wrong?
 …
 } Do not use forwarded-away objects because they may be in moved- from state. ❖ Remember that std::forward may act as std::move. Check previous presentation for std::move and rvalue related concerns. ❖ Remember that universal reference may be either rvalue reference or lvalue reference. Write code accordingly. 18
  • 19. Avoid Overloading on URefs Imagine that we want to differently process rvalues (first overload) and lvalues (second one): template<typename T>
 void foo(T&& t) {… std::move(t); …} // [1] rvalues template<typename T>
 void foo(T const& t) {…} // [2] lvalues std::string s = “wow”;
 foo(s); WTF, overload [1] is called! Only const lvalues go to [2], all the rest including non-const lvalues go to [1] because it takes universal reference ⇒ accepts everything ⇒ a better match for everything except const lvalue ref. 19
  • 20. Avoid Overloading on URefs Imagine that we want to have overload for integers: template<typename T>
 void foo(T&& t) {…} // [1] general case void foo(long t) {…} // [2] integers short s = 42;
 foo(s); WTF, overload [1] is called! Only longs go to [2], all the rest including integers that need to be promoted to long integer go to [1] because it takes universal reference ⇒ accepts everything ⇒ a better match for everything except a long integer. 20
  • 21. Avoid Overloading on URefs ❖ Problem’s root cause is that universal reference parameter is too “greedy” (by purpose) so become a better match more frequently than expected. ❖ There are some solutions (Partially stolen from Meyers’ book): ❖ Abandon overloading by using different function names or different number of parameters. ❖ Pass by const reference instead of universal reference. ❖ Pass params that are movable and copyable by value (and get rid of template that uses universal references at all) ❖ Tag dispatch ❖ Constrain template that uses universal references 21
  • 22. Avoid Overloading on URefs: Tag Dispatch Using of compile time dispatching to implement overloading for rvalues and lvalues: template<typename T>
 void foo(T&& t)
 {
 foo_impl(std::forward<T>(t),
 std::is_lvalue_reference<T>());
 } template<typename T>
 void foo_impl(T&& t, std::true_type) {…} // lvalues template<typename T>
 void foo_impl(T&& t, std::false_type) {…} // rvalues 22
  • 23. URefs And Copy Constructor Consider the simple wrapper: template<typename T>
 struct Wrapper {
 T m_value;
 …
 template<typename U> // Single arg for simplicity
 explicit Wrapper(U&& u)
 : m_value(std::forward<U>(u)) {}
 }; The purpose is to allow to construct Wrapper with whatever wrapped type constructor accepts: Wrapper<std::string> hello_world(“Hello, World!”); 23
  • 24. URefs And Copy Constructor template<typename T>
 struct Wrapper {
 T m_value;
 …
 template<typename U>
 explicit Wrapper(U&& u)
 : m_value(std::forward<U>(u)) {}
 }; Looks OK? Wrapper<std::string> w1(“Hello, World!”);
 Wrapper<std::string> w2(w1); // Compilation error For non-const lvalue reference the forwarding constructor is a better match than [generated] copy constructor: Wrapper(const Wrapper& rhs); 24
  • 25. URefs And Copy Constructor ❖ Copy assignment operator has the same issue. ❖ Variadic forwarding constructor has the same issue. template<typename... Ts>
 struct tuple
 {
 template<typename... Us>
 explicit tuple(Us&&... us);
 // May be chosen instead of copy constructor
 …
 }; 25
  • 26. Constraining URef Template Possible solution is to disable forwarding constructor for Wrapper and derived types: template<typename T>
 struct Wrapper {
 T m_value;
 …
 template<
 typename U,
 typename = disable_if_same_or_derived_t<Wrapper, U>>
 explicit Wrapper(U&& u)
 : m_value(std::forward<U>(u)) {}
 }; template<typename Base, typename Derived>
 using disable_if_same_or_derived_t =
 std::enable_if_t<
 !std::is_base_of<
 Base,
 std::decay_t<Derived>
 >::value
 >; // C++14. A bit more verbose in C++11 26 std::enable_if metafunction is a convenient way to leverage SFINAE to conditionally remove functions from overload resolution based on type traits.
  • 27. Constraining URef Template 2 Another solution is to enable forwarding constructor only for types that may be used to construct T: template<typename T>
 struct Wrapper {
 T m_value;
 …
 template<
 typename U,
 typename = std::enable_if_t<std::is_constructible<T, U&&>::value>>
 explicit Wrapper(U&& u)
 : m_value(std::forward<U>(u)) {}
 }; // C++14. A bit more verbose in C++11 Easily extended to any number of arguments: template<typename T>
 struct Wrapper {
 T m_value;
 …
 template<
 typename... U,
 typename = std::enable_if_t<std::is_constructible<T, U&&...>::value>>
 explicit Wrapper(U&&... u)
 : m_value(std::forward<U>(u)...) {}
 }; // C++14. A bit more verbose in C++11 27
  • 28. Constraining URef Template 3 Another solution is to disable forwarding constructor for types that otherwise convertible to Wrapper. Which is true for Wrapper and derived types, for types that got a dedicated constructor and types that implement a conversion to Wrapper. template<class T>
 struct Wrapper {
 T m_value;
 …
 template<
 typename U,
 typename = std::enable_if_t<!std::is_convertible<U&&, Wrapper>::value>>
 explicit Wrapper(U&& u);
 explicit Wrapper(const Bar& bar); // A dedicated constructor for Bar 
 }; template<class T> struct Foo { operator Wrapper<T> () const; // Foo<T> provides a conversion to Wrapper<T> }; Bar bar; Foo<std::string> foo; Wrapper<std::string> w1(bar), w2(foo); // ^ C++14. A bit more verbose in C++11 28
  • 29. Perfect Forwarding Failures ❖ Braced initializer. Compiler can not deduce the type.
 makeShared<std::vector<int>>({1, 2, 3});
 User has to explicitly specify a type:
 makeShared<std::vector<int>>(
 std::initialized_list<int>({1, 2, 3}));
 or
 auto list = {1, 2, 3};
 makeShared<std::vector<int>>(list); ❖ Overloaded function and function template names. A set of functions that compiler can not choose a right one from.
 You have to explicitly choose one function by casting the function to a specific function pointer type. 29
  • 30. Perfect Forwarding Failures ❖ 0 or NULL as null pointers. They are deduced to integral type instead of pointer type. Use nullptr instead (not only in this case but always!). ❖ Declaration-only static const and constexpr data. Causes linker error. struct Calendar {
 static const int numberOfMonths = 12;
 …
 }; makeShared<int>(Calendar::numberOfMonths); User has to add a definition for the data or pass a copy: makeShared<int>(int(Calendar::numberOfMonths)); ❖ Non-const bit-field. Non-const reference cannot bind to a bit-field. User has to pass a copy: makeShared<int>(int(var.bitField)); 30
  • 31. Useful Links Thomas Becker, Perfect Forwarding: The Problem
 http://thbecker.net/articles/rvalue_references/section_07.html Scott Meyers, Universal References
 http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers Eric Niebler, Universal References and the Copy Constructor
 http://ericniebler.com/2013/08/07/universal-references-and-the-copy-constructo/ (Im)perfect forwarding with variadic templates
 stackoverflow.com/questions/13296461/imperfect-forwarding-with-variadic- templates C++11 Standard (final plus minor editorial changes) http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf Scott Meyers, Effective Modern C++, (Item 1 & chapter 4) 31