SlideShare a Scribd company logo
1 of 71
Download to read offline
Effective Modern C++
勉強会#7
Item 27
刈谷 満(@kariya_mitsuru)
2015/6/17
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
ユニバーサルリファレンスを伴う
オーバーロードの代替案に
慣れ親しもう
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
Item 26 で見たように、ユニバーサルリ
ファレンスを伴うオーバーロードはヤバい
でも、オーバーロード便利
(ただし、思った通りに動いてくれれば)
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
こんな代替案がある
1. オーバーロードを諦める
2. const T& で渡す
3. 値で渡す
4. タグディスパッチを使う
5. ユニバーサルリファレンスをとるテンプレートに
制約を設ける
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
1.オーバーロードを諦める
そのまんま
オーバーロードするから訳が分からなくなる
⇓
オーバーロードしなきゃいんじゃね?
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
これを
template<typename T>
void logAndAdd(T&& name);
void logAndAdd(int idx);
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
これを
template<typename T>
void logAndAdd(T&& name);
void logAndAdd(int idx);
こうじゃ
template<typename T>
void logAndAddName(T&& name);
void logAndAddNameIdx(int idx);
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
これを
template<typename T>
void logAndAdd(T&& name);
void logAndAdd(int idx);
こうじゃ
template<typename T>
void logAndAddName(T&& name);
void logAndAddNameIdx(int idx);
全て解決!
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
欠点
コンストラクタには無力
(コンストラクタには名前が無い)
本には名前固定って書いてあるけど、名前無いっすよ…
§12[class.ctor]/p.1 "Constructors do not have names."
てか、やっぱオーバーロード使いたくね?
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
2.const T& で渡す
そのまんま
ユニバーサルリファレンス使うから訳がわからなくなる
⇓
ユニバーサルリファレンス使わなきゃいんじゃね?
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
これを
template<typename T>
void logAndAdd(T&& name);
void logAndAdd(int idx);
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
これを
template<typename T>
void logAndAdd(T&& name);
void logAndAdd(int idx);
こうじゃ
void logAndAdd(const std::string&
name);
void logAndAdd(int idx);
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
これを
template<typename T>
void logAndAdd(T&& name);
void logAndAdd(int idx);
こうじゃ
void logAndAdd(const std::string&
name);
void logAndAdd(int idx);
全て解決!
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
欠点
ユニバーサルリファレンス使う方法ほど
効率的じゃない
(でもシンプルさは魅力的)
てか、やっぱユニバーサルリファレンス
使いたくね?
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
3.値で渡す
そのまんま
…え?効率は?
実はわりと効率がいい(場合も多い)
けど、詳細は Item 41 のお楽しみ
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
これを
template<typename T>
explicit Person(T&& n)
: name(std::forward<T>(n)) {}
explicit Person(int idx)
: name(nameFromIdx(idx)) {}
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
これを
template<typename T>
explicit Person(T&& n)
: name(std::forward<T>(n)) {}
explicit Person(int idx)
: name(nameFromIdx(idx)) {}
こうじゃ
explicit Person(std::string n)
: name(std::move(n)) {}
explicit Perosn(int idx)
: name(nameFromIdx(idx)) {}
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
これを
template<typename T>
explicit Person(T&& n)
: name(std::forward<T>(n)) {}
explicit Person(int idx)
: name(nameFromIdx(idx)) {}
こうじゃ
explicit Person(std::string n)
: name(std::move(n)) {}
explicit Perosn(int idx)
: name(nameFromIdx(idx)) {}
全て解決!
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
欠点
この例ならわりと効率いいけど、
ユニバーサルリファレンスほどじゃないし、
ムーブが効率悪い場合には使えない。(std::array とか…)
Item 41 を知らない人が見ると、「効率悪い!」と言われて、
最悪直される(※ 個人の感想です)
0 はともかく、NULL を渡すと int バージョン呼ばれる。
(けど、これに限らないし、Item 8 読め)
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
4.タグディスパッチを使う
やっぱ完全転送したい!!!
⇓
みんな大好き、タグディスパッチ
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
わ
あ
い
タ
グ
デ
ィ
ス
パ
ッ
チ
め
う
め
う
タ
グ
デ
ィ
ス
パ
ッ
チ
大
好
き
め
う
©芽兎めう
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
ユニバーサルリファレンスの問題点
あらゆる引数に完全一致する
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
引
数
が
一
つ
し
か
な
い
と
錯
覚
し
て
い
た
?
©藍染惣右介
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
解決策
ユニバーサルリファレンス以外
の引数で、オーバーロード解決
を制御すれば良い
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
元のコード
std::multiset<std::string> names;
template<typename T>
void logAndAdd(T&& name)
{
auto now = std::chrono::system_clock::now();
log(now, "logAndAdd");
names.emplace(std::forward<T>(name));
}
これに、int を取るオーバーロードを追加したい
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
logAndAdd のオーバーロードを追加するんじゃなくて、
logAndAdd 内で実際に処理する関数
logAndAddImpl に処理を委譲する
⇓
この際、T が int の場合用と
そうじゃない場合用の関数を作って
それらの関数に追加の引数を追加して、
それらの型(タグ)が完璧に異なれば良い
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
クライアントが呼び出す関数
template<typename T>
void logAndAdd(T&& name)
{
logAndAddImpl(name,
型①か型②);
}
実際に処理する関数
void logAndAddImpl(T&& name,
型①)
{
int 以外の時の処理がここに
}
void logAndAddImpl(int idx,
型②)
{
int の時の処理がここに
}T が int の以外時は「型①」
T が int の時は「型②」
つまり、こんな感じにすれば良い
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
クライアントが呼び出す関数
template<typename T>
void logAndAdd(T&& name)
{
logAndAddImpl(name,
型①か型②);
}
実際に処理する関数
void logAndAddImpl(T&& name,
型①)
{
int 以外の時の処理がここに
}
void logAndAddImpl(int idx,
型②)
{
int の時の処理がここに
}T が int の以外時は「型①」
T が int の時は「型②」
つまり、こんな感じにすれば良い
で?
「型①か型②」って?
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
これが「型①か型②」だ!!!
template<typename T>
void logAndAdd(T&& name)
{
logAndAddImpl(std::forward<T>(name),
std::is_integral<T>());
}
引数だから、() を付
けてオブジェクト生成
T が int 以外の時は「std::false_type」から派生
T が int の時は「std::true_type」から派生
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
これが「型①か型②」だ!!!
template<typename T>
void logAndAdd(T&& name)
{
logAndAddImpl(std::forward<T>(name),
std::is_integral<T>());
}
引数だから、() を付
けてオブジェクト生成
T が int 以外の時は「std::false_type」から派生
T が int の時は「std::true_type」から派生
でもちょっと
うまくない…
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
int i = 10;
…
logAndAdd(i);
template<typename T>
void logAndAdd(T&& name)
{
logAndAddImpl(
std::forward<T>(name),
std::is_integral<T>());
}
うまくない理由
こんな感じで呼び出すと…
T が int& になっちゃう
⇒参照型は整数型じゃないから、
std::false_typeになっちゃう
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
これが正しい「型①か型②」だ!!!
template<typename T>
void logAndAdd(T&& name)
{
logAndAddImpl(
std::forward<T>(name),
std::is_integral<typename std::remove_reference<T>::type>());
}
T が int っぽくない時は「std::false_type」
T が int っぽい時は「std::true_type」
T から「参照」を消す
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
ちな、処理本体側はこんな感じ
// int 以外用の関数
template<typename T>
void logAndAddImpl(T&& name, std::false_type)
{
auto now = std::chrono::system_clock::now();
log(now, "logAndAdd");
names.emplace(std::forward<T>(name));
}
std::string nameFromIdx(int idx);
// int 用の関数
void logAndAddImpl(int idx, std::true_type)
{
logAndAdd(nameFromIdx(idx));
}
オーバーロード解決の
ためだけにあるから、
パラメータ名は
付けてない
オーバーロード解決の
ためだけにあるから、
パラメータ名は
付けてない
idx から名前に
変換したら、
再度 logAndAdd を
呼び出す
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
ちな、処理本体側はこんな感じ
// int 以外用の関数
template<typename T>
void logAndAddImpl(T&& name, std::false_type)
{
auto now = std::chrono::system_clock::now();
log(now, "logAndAdd");
names.emplace(std::forward<T>(name));
}
std::string nameFromIdx(int idx);
// int 用の関数
void logAndAddImpl(int idx, std::true_type)
{
logAndAdd(nameFromIdx(idx));
}
オーバーロード解決の
ためだけにあるから、
パラメータ名は
付けてない
オーバーロード解決の
ためだけにあるから、
パラメータ名は
付けてない
idx から名前に
変換したら、
再度 logAndAdd を
呼び出す
賢いコンパイラなら、
最後のパラメータ使ってないから
消してくれるかも…
こうすれば、ログ出力コード
二重にメンテしなくて済む…
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
タグディスパッチSUGEEEE!!!!
タグディスパッチのこと
もっと知りたい!!!
でも EMC++ にはそこまで書かれてない…
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
そんなあなたに C++テンプレートテクニック 第2版
あのえぴさんと
アキラさんが
書いてるぞ!!!
C++11
完全対応!!!
電子書籍版も
あるぞ!!!
ちょっと読みづらいけど…
タグディスパッチ
だけじゃなくて
テンプレート
全般!!!
まだ全部理解できてないけど…
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
タグディスパッチいいよ、タグディスパッチ
もう何もかもタグディスパッチでよくね?
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
欠点
コンストラクタには無力
(またっすか…)
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
例のダメなクラス
class Person {
public:
template<typename T>
explicit Person(T&& n)
: name(std::forward<Person&>(n)) {}
explicit Person(int idx);
Person(const Person& rhs);
Person(Person&& rhs);
…
};
完全転送
コンストラクタ
int
コンストラクタ コピー
コンストラクタ
ムーブ
コンストラクタ
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
例のダメなクラス
class Person {
public:
template<typename T>
explicit Person(T&& n)
: name(std::forward<Person&>(n)) {}
explicit Person(int idx);
Person(const Person& rhs);
Person(Person&& rhs);
…
};
Person p("Nancy");
auto cloneOfP(p);
全部完全転送…
上はいいけど、下に対して
コピーコンストラクタが
呼ばれない…
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
5.ユニバーサルリファレンスをとるテンプレートに制約を設ける
そのまんま
ユニバーサルリファレンスを取る関数が
呼ばれて欲しくない時まで呼ばれちゃう
⇓
関数を呼ばれて欲しい時だけ
有効にすればいんじゃね?
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
「関数を呼ばれて欲しい時だけ有効に」?
そのためのメタ関数が type_traits に!
std::enable_if
SFINAE と呼ばれる
機構を使ってる
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
使い方はこんな感じ
class Person {
public:
template<typename T,
typename = typename std::enable_if<condition>::type>
explicit Person(T&& n);
…
}; この condition の部分に、このコンストラク
タを使っても良い条件式を書く。
ただし、コンパイル時定数のみ!!
関数テンプレートのデフォルトテンプレート引数
(C++11の新機能!)を enable_if にする
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
では、今回の場合、どんな時に呼ばれて欲しいのか?
⇓
T が Person じゃない時
T が Person の場合、コピーコンストラクタや
ムーブコンストラクタが呼ばれて欲しいから
そんな時も type_traits
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
こんな式
!std::is_same<Person, T>::value
先頭の!に注意 Person と T が
同じ型の時 true
型じゃなくて
bool 値が欲しいから
::value
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
class Person {
public:
template<
typename T,
typename = typename std::enable_if<
!std::is_same<Person, T>::value
>::type
>
explicit Person(T&& n);
Person(const Person&);
Person(Person&&);
…
};
ダメでした…
Person p("Nancy");
auto cloneOfP(p);
T は
const char(&)[6]
T は
Person&
p は左辺値だから
T が左辺値参照に…
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
T と Person を比較する時には、以下の2点を無視したい
• 参照かどうか
引数の型が Person だろうが Person& だろうが Person&& だろうが、
完全転送コンストラクタじゃ無くてコピー・ムーブコンストラクタが呼ばれてほしい
• const や volatile が付いているかどうか
引数の型が const Person だろうが volatile Person だろうが const volatile
Person だろうが、完全転送コンストラクタじゃ無k(以下略
そんな時も type_traits
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
こんな式
!std::is_same<Person,
typename std::decay<T>::type
>::value
ホントはこれだと、配列や関数をポインタに変換しちゃうけど、今回の場合は問題なし
参照を取ってから、
更に cv 修飾を取る!!
値じゃなくて型が
欲しいから ::type
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
class Person {
public:
template<
typename T,
typename = typename std::enable_if<
!std::is_same<
Person,
typename std::decay<T>::type
>::value
>::type
>
explicit Person(T&& n);
Person(const Person&);
Person(Person&&);
…
};
まだダメでした…
class SP : public Person {
public:
SP(const SP& rhs)
: Person(rhs)
{ … }
SP(SP&& rhs)
: Person(std::move(rhs))
{ … }
…
};
T は
const SP&
T は
SP&&
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
完全転送コンストラクタは、
T が Person かその派生クラスの時には
無効化されて欲しい
そんな時も type_traits
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
class Person {
public:
template<
typename T,
typename = typename std::enable_if<
!std::is_base_of<Person,
typename std::decay<T>::type
>::value
>::type
>
explicit Person(T&& n);
…
};
typename std::decay<T>::type が
Person の派生クラスの時 true
Person そのものでもOK!
だいぶ長い…
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
class Person {
public:
template<
typename T,
typename = typename std::enable_if<
!std::is_base_of<Person,
typename std::decay<T>::type
>::value
>::type
>
explicit Person(T&& n);
…
};
typename std::decay<T>::type が
Person の派生クラスの時 true
Person そのものでもOK!
だいぶ長い…
Errata に補足あり!
std::is_base_of<int, int> は
false になるよ!
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
class Person {
public:
template<
typename T,
typename = std::enable_if_t<
!std::is_base_of<Person,
std::decay_t<T>
>::value
>
>
explicit Person(T&& n);
…
};
ちなみに C++14 だったら
もうちょっとスマート(かな?)
typename と ::type が
必要ない!
C++14 でも ::value は必要
(大人の事情により _v は入らず…)
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
でもまだ int を引数にとる
コンストラクタが追加されてない…
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
class Person {
public:
template<typename T,
typename = std::enable_if_t<
!std::is_base_of<Person, std::decay_t<T>>::value
&&
!std::is_integral<std::remove_reference_t<T>>::value
>
>
explicit Person(T&& n)
: name(std::forward<T>(n))
{ … }
explicit Person(int idx)
: name(nameFromIdx(idx))
{ … }
…
private:
std::string name;
};
C++14 でも
超絶長い…
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
SFINAE SUGEEEE!!!!
SFINAEのこと
もっと知りたい!!!
でも EMC++ にはそこまで書かれてない…
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
そんなあなたに C++テンプレートテクニック 第2版
あのえぴさんと
アキラさんが
書いてるぞ!!!
C++11
完全対応!!!
電子書籍版も
あるぞ!!!
ちょっと読みづらいけど…
SFINAE
だけじゃなくて
テンプレート
全般!!!
まだ全部理解できてないけど…
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
トレードオフ
1. オーバーロードを諦める
2. const T& で渡す
3. 値で渡す
4. タグディスパッチを使う
5. ユニバーサルリファレンスをとる
テンプレートに制約を設ける
完全転送を
諦める
(シンプル)
完全転送を
使う
(効率いい)
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
完全転送の欠点
1.完全転送できない場合がある
(完全じゃね~し… Item 30を参照)
2.クライアントが誤った引数を渡した時、
とち狂ったエラーメッセージが出る
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
とち狂ったメッセージの例
例えば、こんな感じに間違った場合…
Person p(u"Konrad Zuse");
巷で話題の
utf-16 リテラル
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
prog.cc: In instantiation of 'Person::Person(T&&) [with T = const char32_t (&)[5]; <template-parameter-1-2> = void]':
prog.cc:30:18: required from here
prog.cc:16:27: error: no matching function for call to 'std::__cxx11::basic_string<char>::basic_string(const char32_t [5])'
: name(std::forward<T>(n))
^
In file included from /usr/local/gcc-head/include/c++/6.0.0/string:52:0,
from prog.cc:2:
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:535:9: note: candidate: template<class _InputIterator, class> std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(_InputIterator, _InputIterator, const _Alloc&)
basic_string(_InputIterator __beg, _InputIterator __end,
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:535:9: note: template argument deduction/substitution failed:
prog.cc:16:27: note: candidate expects 3 arguments, 1 provided
: name(std::forward<T>(n))
^
In file included from /usr/local/gcc-head/include/c++/6.0.0/string:52:0,
from prog.cc:2:
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:512:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&&, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc =
std::allocator<char>]
basic_string(basic_string&& __str, const _Alloc& __a)
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:512:7: note: candidate expects 2 arguments, 1 provided
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:508:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc =
std::allocator<char>]
basic_string(const basic_string& __str, const _Alloc& __a)
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:508:7: note: candidate expects 2 arguments, 1 provided
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:504:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::initializer_list<_Tp>, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string(initializer_list<_CharT> __l, const _Alloc& __a = _Alloc())
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:504:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'std::initializer_list<char>'
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:477:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string(basic_string&& __str) noexcept
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:477:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'std::__cxx11::basic_string<char>&&'
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:465:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type, _CharT, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>;
_Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]
basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc())
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:465:7: note: candidate expects 3 arguments, 1 provided
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:455:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:455:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'const char*'
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:445:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type, const _Alloc&) [with _CharT = char; _Traits =
std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]
basic_string(const _CharT* __s, size_type __n,
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:445:7: note: candidate expects 3 arguments, 1 provided
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:427:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type,
std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]
basic_string(const basic_string& __str, size_type __pos,
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:427:7: note: candidate expects 4 arguments, 1 provided
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:411:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type,
std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]
basic_string(const basic_string& __str, size_type __pos,
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:411:7: note: candidate expects 3 arguments, 1 provided
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:399:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string(const basic_string& __str)
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:399:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'const std::__cxx11::basic_string<char>&'
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:391:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string(const _Alloc& __a)
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:391:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'const std::allocator<char>&'
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:380:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string() [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string()
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:380:7: note: candidate expects 0 arguments, 1 provided
GCC さん
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
prog.cc:16:4: error: no matching constructor for initialization of 'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >')
: name(std::forward<T>(n))
^ ~~~~~~~~~~~~~~~~~~
prog.cc:30:9: note: in instantiation of function template specialization 'Person::Person<char32_t const (&)[5], void>' requested here
Person p(U"name");
^
/usr/local/libcxx-head/include/c++/v1/string:1326:40: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'const allocator_type' (aka 'const std::__1::allocator<char>') for 1st argument
_LIBCPP_INLINE_VISIBILITY explicit basic_string(const allocator_type& __a)
^
/usr/local/libcxx-head/include/c++/v1/string:1333:5: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'const std::__1::basic_string<char>' for 1st argument
basic_string(const basic_string& __str);
^
/usr/local/libcxx-head/include/c++/v1/string:1338:5: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'std::__1::basic_string<char>' for 1st argument
basic_string(basic_string&& __str)
^
/usr/local/libcxx-head/include/c++/v1/string:1348:31: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'const value_type *' (aka 'const char *') for 1st argument
_LIBCPP_INLINE_VISIBILITY basic_string(const value_type* __s);
^
/usr/local/libcxx-head/include/c++/v1/string:1369:5: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'initializer_list<value_type>' for 1st argument
basic_string(initializer_list<value_type> __il);
^
/usr/local/libcxx-head/include/c++/v1/string:1363:9: note: candidate constructor template not viable: requires 2 arguments, but 1 was provided
basic_string(_InputIterator __first, _InputIterator __last);
^
/usr/local/libcxx-head/include/c++/v1/string:1366:9: note: candidate constructor template not viable: requires 3 arguments, but 1 was provided
basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a);
^
/usr/local/libcxx-head/include/c++/v1/string:1323:31: note: candidate constructor not viable: requires 0 arguments, but 1 was provided
_LIBCPP_INLINE_VISIBILITY basic_string()
^
/usr/local/libcxx-head/include/c++/v1/string:1346:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided
basic_string(basic_string&& __str, const allocator_type& __a);
^
/usr/local/libcxx-head/include/c++/v1/string:1334:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided
basic_string(const basic_string& __str, const allocator_type& __a);
^
/usr/local/libcxx-head/include/c++/v1/string:1350:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided
basic_string(const value_type* __s, const allocator_type& __a);
^
/usr/local/libcxx-head/include/c++/v1/string:1352:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided
basic_string(const value_type* __s, size_type __n);
^
/usr/local/libcxx-head/include/c++/v1/string:1356:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided
basic_string(size_type __n, value_type __c);
^
/usr/local/libcxx-head/include/c++/v1/string:1371:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided
basic_string(initializer_list<value_type> __il, const allocator_type& __a);
^
/usr/local/libcxx-head/include/c++/v1/string:1354:5: note: candidate constructor not viable: requires 3 arguments, but 1 was provided
basic_string(const value_type* __s, size_type __n, const allocator_type& __a);
^
/usr/local/libcxx-head/include/c++/v1/string:1358:5: note: candidate constructor not viable: requires 3 arguments, but 1 was provided
basic_string(size_type __n, value_type __c, const allocator_type& __a);
^
/usr/local/libcxx-head/include/c++/v1/string:1359:5: note: candidate constructor not viable: requires at least 2 arguments, but 1 was provided
basic_string(const basic_string& __str, size_type __pos, size_type __n = npos,
^
Clang さん
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
この例の場合、
ユニバーサルリファレンスの引数は
std::string の初期化に使われることが
分かっているので、
static_assert でチェックすることはできる。
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
class Person {
public:
template<typename T,
typename = std::enable_if_t<
!std::is_base_of<Person, std::decay_t<T>>::value
&&
!std::is_integral<std::remove_reference_t<T>>::value
>
>
explicit Person(T&& n)
: name(std::forward<T>(n))
{
// assert that a std::string can be created from a T object
static_assert(
std::is_constructible<std::string, T>::value,
"Parameter n can't be used to construct a std::string"
);
…
}
…
};
こんな感じでチェック!
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
prog.cc: In instantiation of 'Person::Person(T&&) [with T = const char32_t (&)[5]; <template-parameter-1-2> = void]':
prog.cc:35:18: required from here
prog.cc:16:27: error: no matching function for call to 'std::__cxx11::basic_string<char>::basic_string(const char32_t [5])'
: name(std::forward<T>(n))
^
In file included from /usr/local/gcc-head/include/c++/6.0.0/string:52:0,
from prog.cc:2:
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:535:9: note: candidate: template<class _InputIterator, class> std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(_InputIterator, _InputIterator, const _Alloc&)
basic_string(_InputIterator __beg, _InputIterator __end,
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:535:9: note: template argument deduction/substitution failed:
prog.cc:16:27: note: candidate expects 3 arguments, 1 provided
: name(std::forward<T>(n))
^
In file included from /usr/local/gcc-head/include/c++/6.0.0/string:52:0,
from prog.cc:2:
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:512:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&&, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc =
std::allocator<char>]
basic_string(basic_string&& __str, const _Alloc& __a)
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:512:7: note: candidate expects 2 arguments, 1 provided
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:508:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc =
std::allocator<char>]
basic_string(const basic_string& __str, const _Alloc& __a)
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:508:7: note: candidate expects 2 arguments, 1 provided
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:504:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::initializer_list<_Tp>, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string(initializer_list<_CharT> __l, const _Alloc& __a = _Alloc())
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:504:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'std::initializer_list<char>'
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:477:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string(basic_string&& __str) noexcept
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:477:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'std::__cxx11::basic_string<char>&&'
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:465:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type, _CharT, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>;
_Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]
basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc())
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:465:7: note: candidate expects 3 arguments, 1 provided
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:455:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:455:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'const char*'
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:445:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type, const _Alloc&) [with _CharT = char; _Traits =
std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]
basic_string(const _CharT* __s, size_type __n,
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:445:7: note: candidate expects 3 arguments, 1 provided
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:427:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type,
std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]
basic_string(const basic_string& __str, size_type __pos,
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:427:7: note: candidate expects 4 arguments, 1 provided
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:411:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type,
std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]
basic_string(const basic_string& __str, size_type __pos,
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:411:7: note: candidate expects 3 arguments, 1 provided
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:399:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string(const basic_string& __str)
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:399:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'const std::__cxx11::basic_string<char>&'
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:391:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string(const _Alloc& __a)
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:391:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'const std::allocator<char>&'
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:380:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string() [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string()
^
/usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:380:7: note: candidate expects 0 arguments, 1 provided
prog.cc:19:3: error: static assertion failed: Parameter n can't be used to construct a std::string
static_assert(
^
GCC さん
ここ!
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
prog.cc:16:4: error: no matching constructor for initialization of 'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >')
: name(std::forward<T>(n))
^ ~~~~~~~~~~~~~~~~~~
prog.cc:35:9: note: in instantiation of function template specialization 'Person::Person<char32_t const (&)[5], void>' requested here
Person p(U"name");
^
/usr/local/libcxx-head/include/c++/v1/string:1326:40: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'const allocator_type' (aka 'const std::__1::allocator<char>') for 1st argument
_LIBCPP_INLINE_VISIBILITY explicit basic_string(const allocator_type& __a)
^
/usr/local/libcxx-head/include/c++/v1/string:1333:5: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'const std::__1::basic_string<char>' for 1st argument
basic_string(const basic_string& __str);
^
/usr/local/libcxx-head/include/c++/v1/string:1338:5: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'std::__1::basic_string<char>' for 1st argument
basic_string(basic_string&& __str)
^
/usr/local/libcxx-head/include/c++/v1/string:1348:31: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'const value_type *' (aka 'const char *') for 1st argument
_LIBCPP_INLINE_VISIBILITY basic_string(const value_type* __s);
^
/usr/local/libcxx-head/include/c++/v1/string:1369:5: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'initializer_list<value_type>' for 1st argument
basic_string(initializer_list<value_type> __il);
^
/usr/local/libcxx-head/include/c++/v1/string:1363:9: note: candidate constructor template not viable: requires 2 arguments, but 1 was provided
basic_string(_InputIterator __first, _InputIterator __last);
^
/usr/local/libcxx-head/include/c++/v1/string:1366:9: note: candidate constructor template not viable: requires 3 arguments, but 1 was provided
basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a);
^
/usr/local/libcxx-head/include/c++/v1/string:1323:31: note: candidate constructor not viable: requires 0 arguments, but 1 was provided
_LIBCPP_INLINE_VISIBILITY basic_string()
^
/usr/local/libcxx-head/include/c++/v1/string:1346:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided
basic_string(basic_string&& __str, const allocator_type& __a);
^
/usr/local/libcxx-head/include/c++/v1/string:1334:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided
basic_string(const basic_string& __str, const allocator_type& __a);
^
/usr/local/libcxx-head/include/c++/v1/string:1350:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided
basic_string(const value_type* __s, const allocator_type& __a);
^
/usr/local/libcxx-head/include/c++/v1/string:1352:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided
basic_string(const value_type* __s, size_type __n);
^
/usr/local/libcxx-head/include/c++/v1/string:1356:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided
basic_string(size_type __n, value_type __c);
^
/usr/local/libcxx-head/include/c++/v1/string:1371:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided
basic_string(initializer_list<value_type> __il, const allocator_type& __a);
^
/usr/local/libcxx-head/include/c++/v1/string:1354:5: note: candidate constructor not viable: requires 3 arguments, but 1 was provided
basic_string(const value_type* __s, size_type __n, const allocator_type& __a);
^
/usr/local/libcxx-head/include/c++/v1/string:1358:5: note: candidate constructor not viable: requires 3 arguments, but 1 was provided
basic_string(size_type __n, value_type __c, const allocator_type& __a);
^
/usr/local/libcxx-head/include/c++/v1/string:1359:5: note: candidate constructor not viable: requires at least 2 arguments, but 1 was provided
basic_string(const basic_string& __str, size_type __pos, size_type __n = npos,
^
prog.cc:19:3: error: static_assert failed "Parameter n can't be used to construct a std::string"
static_assert(
^
Clang さん
ここ!
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
でも、今回の例の場合、
ホントはそもそも std::enable_if の条件に
std::is_constructible 使えばいいと
思うんだけど…
Errata には、コンパイラのエラーメッセージが、
「そんなコンストラクタ無いよ」ってなるので、
意味が変わっちゃうって書いてあるけど…
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
こんな感じ
class Person {
public:
template<typename T,
typename = std::enable_if_t<std::is_constructible<std::string, T>::value>
>
explicit Person(T&& n)
: name(std::forward<T>(n))
{
…
}
…
};
こんな感じで無効化!
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
prog.cc: In function 'int main()':
prog.cc:26:18: error: no matching function for call to 'Person::Person(const char32_t [5])'
Person p(U"name");
^
prog.cc:18:2: note: candidate: Person::Person(Person&&)
Person(Person&&) = default;
^
prog.cc:18:2: note: no known conversion for argument 1 from 'const char32_t [5]' to
'Person&&'
prog.cc:17:2: note: candidate: Person::Person(const Person&)
Person(const Person&) = default;
^
prog.cc:17:2: note: no known conversion for argument 1 from 'const char32_t [5]' to 'const
Person&'
prog.cc:11:11: note: candidate: template<class T, class> Person::Person(T&&)
explicit Person(T&& n)
^
prog.cc:11:11: note: template argument deduction/substitution failed:
GCC さん
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
prog.cc:26:9: error: no matching constructor for initialization of 'Person'
Person p(U"name");
^ ~~~~~~~
prog.cc:17:2: note: candidate constructor not viable: no known conversion from 'const
char32_t [5]' to 'const Person' for 1st argument
Person(const Person&) = default;
^
prog.cc:18:2: note: candidate constructor not viable: no known conversion from 'const
char32_t [5]' to 'Person' for 1st argument
Person(Person&&) = default;
^
/usr/local/libcxx-head/include/c++/v1/type_traits:244:78: note: candidate template ignored:
disabled by 'enable_if' [with T = char32_t const (&)[5]]
template <bool _Bp, class _Tp = void> using enable_if_t = typename enable_if<_Bp,
_Tp>::type;
^
Clang さん
Clang さんすごい!
Item 27: Familiarize yourself with alternatives
to overloading on universal references.
覚えておくこと
• ユニバーサルリファレンスとオーバーロードの組み合わせの代替案
には、異なる関数名を使用する、パラメータをconstへの左辺値参
照で渡す、パラメータを値で渡す、タグディスパッチを使う、が含まれ
る。
• std::enable_if を通じてテンプレートを制約することで、ユニ
バーサルリファレンスとオーバーロードを同時に使用できるが、それ
はコンパイラがユニバーサルリファレンスのオーバーロードを使用す
る条件を制御する。
• ユニバーサルリファレンスはたいてい効率上の利点があるが、概し
て使い勝手の点で欠点もある。

More Related Content

What's hot

Effective Modern C++ Item 9 and 10
Effective Modern C++ Item 9 and 10Effective Modern C++ Item 9 and 10
Effective Modern C++ Item 9 and 10uchan_nos
 
Effective Modern C++勉強会#4 Item 17, 18資料
Effective Modern C++勉強会#4 Item 17, 18資料Effective Modern C++勉強会#4 Item 17, 18資料
Effective Modern C++勉強会#4 Item 17, 18資料Ryo Igarashi
 
クロージャデザインパターン
クロージャデザインパターンクロージャデザインパターン
クロージャデザインパターンMoriharu Ohzu
 
Boost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
Boost.勉強会#19東京 Effective Modern C++とC++ Core GuidelinesBoost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
Boost.勉強会#19東京 Effective Modern C++とC++ Core GuidelinesShintarou Okada
 
闇魔術を触ってみた
闇魔術を触ってみた闇魔術を触ってみた
闇魔術を触ってみたSatoshi Sato
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門Hideyuki Tanaka
 
C++ マルチスレッドプログラミング
C++ マルチスレッドプログラミングC++ マルチスレッドプログラミング
C++ マルチスレッドプログラミングKohsuke Yuasa
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexprGenya Murakami
 
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!Genya Murakami
 
新しい並列for構文のご提案
新しい並列for構文のご提案新しい並列for構文のご提案
新しい並列for構文のご提案yohhoy
 
コンピュータシステムの理論と実装1
コンピュータシステムの理論と実装1コンピュータシステムの理論と実装1
コンピュータシステムの理論と実装1H T
 
規格書で読むC++11のスレッド
規格書で読むC++11のスレッド規格書で読むC++11のスレッド
規格書で読むC++11のスレッドKohsuke Yuasa
 
Constexpr 中3女子テクニック
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニックGenya Murakami
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるHideyuki Tanaka
 
きつねさんでもわかるLlvm読書会 第2回
きつねさんでもわかるLlvm読書会 第2回きつねさんでもわかるLlvm読書会 第2回
きつねさんでもわかるLlvm読書会 第2回Tomoya Kawanishi
 
不遇の標準ライブラリ - valarray
不遇の標準ライブラリ - valarray不遇の標準ライブラリ - valarray
不遇の標準ライブラリ - valarrayRyosuke839
 

What's hot (20)

Effective Modern C++ Item 9 and 10
Effective Modern C++ Item 9 and 10Effective Modern C++ Item 9 and 10
Effective Modern C++ Item 9 and 10
 
Effective Modern C++勉強会#4 Item 17, 18資料
Effective Modern C++勉強会#4 Item 17, 18資料Effective Modern C++勉強会#4 Item 17, 18資料
Effective Modern C++勉強会#4 Item 17, 18資料
 
クロージャデザインパターン
クロージャデザインパターンクロージャデザインパターン
クロージャデザインパターン
 
Boost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
Boost.勉強会#19東京 Effective Modern C++とC++ Core GuidelinesBoost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
Boost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
 
闇魔術を触ってみた
闇魔術を触ってみた闇魔術を触ってみた
闇魔術を触ってみた
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門
 
C++ マルチスレッドプログラミング
C++ マルチスレッドプログラミングC++ マルチスレッドプログラミング
C++ マルチスレッドプログラミング
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexpr
 
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!
 
新しい並列for構文のご提案
新しい並列for構文のご提案新しい並列for構文のご提案
新しい並列for構文のご提案
 
コンピュータシステムの理論と実装1
コンピュータシステムの理論と実装1コンピュータシステムの理論と実装1
コンピュータシステムの理論と実装1
 
規格書で読むC++11のスレッド
規格書で読むC++11のスレッド規格書で読むC++11のスレッド
規格書で読むC++11のスレッド
 
llvm入門
llvm入門llvm入門
llvm入門
 
入門 シェル実装
入門 シェル実装入門 シェル実装
入門 シェル実装
 
Constexpr 中3女子テクニック
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニック
 
Monad tutorial
Monad tutorialMonad tutorial
Monad tutorial
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISる
 
きつねさんでもわかるLlvm読書会 第2回
きつねさんでもわかるLlvm読書会 第2回きつねさんでもわかるLlvm読書会 第2回
きつねさんでもわかるLlvm読書会 第2回
 
Lockfree Queue
Lockfree QueueLockfree Queue
Lockfree Queue
 
不遇の標準ライブラリ - valarray
不遇の標準ライブラリ - valarray不遇の標準ライブラリ - valarray
不遇の標準ライブラリ - valarray
 

Viewers also liked

Effective modern C++ 勉強会 #3 Item 12
Effective modern C++ 勉強会 #3 Item 12Effective modern C++ 勉強会 #3 Item 12
Effective modern C++ 勉強会 #3 Item 12Keisuke Fukuda
 
Effective Modern C++ 勉強会 Item 22
Effective Modern C++ 勉強会 Item 22Effective Modern C++ 勉強会 Item 22
Effective Modern C++ 勉強会 Item 22Keisuke Fukuda
 
Effective Modern C++ study group Item39
Effective Modern C++ study group Item39Effective Modern C++ study group Item39
Effective Modern C++ study group Item39Takatoshi Kondo
 
Effective Modern C++ 勉強会#3 Item 15
Effective Modern C++ 勉強会#3 Item 15Effective Modern C++ 勉強会#3 Item 15
Effective Modern C++ 勉強会#3 Item 15Mitsuru Kariya
 
Effective Modern C++勉強会#2 Item 11(,12)
Effective Modern C++勉強会#2 Item 11(,12)Effective Modern C++勉強会#2 Item 11(,12)
Effective Modern C++勉強会#2 Item 11(,12)Keisuke Fukuda
 
Effective Modern C++ 勉強会#6 Item25
Effective Modern C++ 勉強会#6 Item25Effective Modern C++ 勉強会#6 Item25
Effective Modern C++ 勉強会#6 Item25Takashi Hoshino
 
Effective Modern C++ 勉強会#8 Item38
Effective Modern C++ 勉強会#8 Item38Effective Modern C++ 勉強会#8 Item38
Effective Modern C++ 勉強会#8 Item38Takashi Hoshino
 
Effective modern c++ 8
Effective modern c++ 8Effective modern c++ 8
Effective modern c++ 8uchan_nos
 
Effective Modern C++ Item 24: Distinguish universal references from rvalue re...
Effective Modern C++ Item 24: Distinguish universal references from rvalue re...Effective Modern C++ Item 24: Distinguish universal references from rvalue re...
Effective Modern C++ Item 24: Distinguish universal references from rvalue re...mooopan
 
Effective Modern C++ 読書会 Item 35
Effective Modern C++ 読書会 Item 35Effective Modern C++ 読書会 Item 35
Effective Modern C++ 読書会 Item 35Keisuke Fukuda
 
Effective modern c++ 5
Effective modern c++ 5Effective modern c++ 5
Effective modern c++ 5uchan_nos
 

Viewers also liked (18)

Effective modern-c++#9
Effective modern-c++#9Effective modern-c++#9
Effective modern-c++#9
 
emc++ chapter32
emc++ chapter32emc++ chapter32
emc++ chapter32
 
Effective modern C++ 勉強会 #3 Item 12
Effective modern C++ 勉強会 #3 Item 12Effective modern C++ 勉強会 #3 Item 12
Effective modern C++ 勉強会 #3 Item 12
 
Effective Modern C++ 勉強会 Item 22
Effective Modern C++ 勉強会 Item 22Effective Modern C++ 勉強会 Item 22
Effective Modern C++ 勉強会 Item 22
 
Effective Modern C++ study group Item39
Effective Modern C++ study group Item39Effective Modern C++ study group Item39
Effective Modern C++ study group Item39
 
Effective Modern C++ 勉強会#3 Item 15
Effective Modern C++ 勉強会#3 Item 15Effective Modern C++ 勉強会#3 Item 15
Effective Modern C++ 勉強会#3 Item 15
 
Effective Modern C++勉強会#2 Item 11(,12)
Effective Modern C++勉強会#2 Item 11(,12)Effective Modern C++勉強会#2 Item 11(,12)
Effective Modern C++勉強会#2 Item 11(,12)
 
Effective Modern C++ 勉強会#6 Item25
Effective Modern C++ 勉強会#6 Item25Effective Modern C++ 勉強会#6 Item25
Effective Modern C++ 勉強会#6 Item25
 
Effective Modern C++ 勉強会#8 Item38
Effective Modern C++ 勉強会#8 Item38Effective Modern C++ 勉強会#8 Item38
Effective Modern C++ 勉強会#8 Item38
 
Effective modern c++ 8
Effective modern c++ 8Effective modern c++ 8
Effective modern c++ 8
 
Effective Modern C++ Item 24: Distinguish universal references from rvalue re...
Effective Modern C++ Item 24: Distinguish universal references from rvalue re...Effective Modern C++ Item 24: Distinguish universal references from rvalue re...
Effective Modern C++ Item 24: Distinguish universal references from rvalue re...
 
Emcjp item33,34
Emcjp item33,34Emcjp item33,34
Emcjp item33,34
 
emcjp Item 42
emcjp Item 42emcjp Item 42
emcjp Item 42
 
Emcjp item21
Emcjp item21Emcjp item21
Emcjp item21
 
Emcpp item31
Emcpp item31Emcpp item31
Emcpp item31
 
Emcpp item41
Emcpp item41Emcpp item41
Emcpp item41
 
Effective Modern C++ 読書会 Item 35
Effective Modern C++ 読書会 Item 35Effective Modern C++ 読書会 Item 35
Effective Modern C++ 読書会 Item 35
 
Effective modern c++ 5
Effective modern c++ 5Effective modern c++ 5
Effective modern c++ 5
 

Similar to Effective Modern C++ 勉強会#7 Item 27

Hot С++: Universal References And Perfect Forwarding
Hot С++: Universal References And Perfect ForwardingHot С++: Universal References And Perfect Forwarding
Hot С++: Universal References And Perfect ForwardingAndrey Upadyshev
 
[OLD VERSION, SEE DESCRIPTION FOR THE NEWER VERSION LINK] Hot С++: Universal ...
[OLD VERSION, SEE DESCRIPTION FOR THE NEWER VERSION LINK] Hot С++: Universal ...[OLD VERSION, SEE DESCRIPTION FOR THE NEWER VERSION LINK] Hot С++: Universal ...
[OLD VERSION, SEE DESCRIPTION FOR THE NEWER VERSION LINK] Hot С++: Universal ...Andrey Upadyshev
 
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.0Yaser Zhian
 
Big Brother helps you
Big Brother helps youBig Brother helps you
Big Brother helps youPVS-Studio
 
OpenGurukul : Language : C Programming
OpenGurukul : Language : C ProgrammingOpenGurukul : Language : C Programming
OpenGurukul : Language : C ProgrammingOpen Gurukul
 
Types Working for You, Not Against You
Types Working for You, Not Against YouTypes Working for You, Not Against You
Types Working for You, Not Against YouC4Media
 
More Little Wonders of C#/.NET
More Little Wonders of C#/.NETMore Little Wonders of C#/.NET
More Little Wonders of C#/.NETBlackRabbitCoder
 
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 ForwardingFrancesco Casalegno
 
What's next in Julia
What's next in JuliaWhat's next in Julia
What's next in JuliaJiahao Chen
 
The TclQuadcode Compiler
The TclQuadcode CompilerThe TclQuadcode Compiler
The TclQuadcode CompilerDonal Fellows
 
Complex C-declarations & typedef
Complex C-declarations & typedefComplex C-declarations & typedef
Complex C-declarations & typedefSaurav Mukherjee
 
JAVA Tutorial- Do's and Don'ts of Java programming
JAVA Tutorial- Do's and Don'ts of Java programmingJAVA Tutorial- Do's and Don'ts of Java programming
JAVA Tutorial- Do's and Don'ts of Java programmingKeshav Kumar
 
JAVA Tutorial- Do's and Don'ts of Java programming
JAVA Tutorial- Do's and Don'ts of Java programmingJAVA Tutorial- Do's and Don'ts of Java programming
JAVA Tutorial- Do's and Don'ts of Java programmingKeshav Kumar
 

Similar to Effective Modern C++ 勉強会#7 Item 27 (20)

Hot С++: Universal References And Perfect Forwarding
Hot С++: Universal References And Perfect ForwardingHot С++: Universal References And Perfect Forwarding
Hot С++: Universal References And Perfect Forwarding
 
[OLD VERSION, SEE DESCRIPTION FOR THE NEWER VERSION LINK] Hot С++: Universal ...
[OLD VERSION, SEE DESCRIPTION FOR THE NEWER VERSION LINK] Hot С++: Universal ...[OLD VERSION, SEE DESCRIPTION FOR THE NEWER VERSION LINK] Hot С++: Universal ...
[OLD VERSION, SEE DESCRIPTION FOR THE NEWER VERSION LINK] Hot С++: Universal ...
 
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
 
Big Brother helps you
Big Brother helps youBig Brother helps you
Big Brother helps you
 
OpenGurukul : Language : C Programming
OpenGurukul : Language : C ProgrammingOpenGurukul : Language : C Programming
OpenGurukul : Language : C Programming
 
Types Working for You, Not Against You
Types Working for You, Not Against YouTypes Working for You, Not Against You
Types Working for You, Not Against You
 
More Little Wonders of C#/.NET
More Little Wonders of C#/.NETMore Little Wonders of C#/.NET
More Little Wonders of C#/.NET
 
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
 
What's next in Julia
What's next in JuliaWhat's next in Julia
What's next in Julia
 
The TclQuadcode Compiler
The TclQuadcode CompilerThe TclQuadcode Compiler
The TclQuadcode Compiler
 
C tutorial
C tutorialC tutorial
C tutorial
 
Simple Design
Simple DesignSimple Design
Simple Design
 
C# overview part 1
C# overview part 1C# overview part 1
C# overview part 1
 
Python cheat-sheet
Python cheat-sheetPython cheat-sheet
Python cheat-sheet
 
Creating classes and applications in java
Creating classes and applications in javaCreating classes and applications in java
Creating classes and applications in java
 
Complex C-declarations & typedef
Complex C-declarations & typedefComplex C-declarations & typedef
Complex C-declarations & typedef
 
Lập trình C
Lập trình CLập trình C
Lập trình C
 
JAVA Tutorial- Do's and Don'ts of Java programming
JAVA Tutorial- Do's and Don'ts of Java programmingJAVA Tutorial- Do's and Don'ts of Java programming
JAVA Tutorial- Do's and Don'ts of Java programming
 
JAVA Tutorial- Do's and Don'ts of Java programming
JAVA Tutorial- Do's and Don'ts of Java programmingJAVA Tutorial- Do's and Don'ts of Java programming
JAVA Tutorial- Do's and Don'ts of Java programming
 

Recently uploaded

How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfhans926745
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 

Recently uploaded (20)

How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 

Effective Modern C++ 勉強会#7 Item 27

  • 1. Effective Modern C++ 勉強会#7 Item 27 刈谷 満(@kariya_mitsuru) 2015/6/17
  • 2. Item 27: Familiarize yourself with alternatives to overloading on universal references. ユニバーサルリファレンスを伴う オーバーロードの代替案に 慣れ親しもう
  • 3. Item 27: Familiarize yourself with alternatives to overloading on universal references. Item 26 で見たように、ユニバーサルリ ファレンスを伴うオーバーロードはヤバい でも、オーバーロード便利 (ただし、思った通りに動いてくれれば)
  • 4. Item 27: Familiarize yourself with alternatives to overloading on universal references. こんな代替案がある 1. オーバーロードを諦める 2. const T& で渡す 3. 値で渡す 4. タグディスパッチを使う 5. ユニバーサルリファレンスをとるテンプレートに 制約を設ける
  • 5. Item 27: Familiarize yourself with alternatives to overloading on universal references. 1.オーバーロードを諦める そのまんま オーバーロードするから訳が分からなくなる ⇓ オーバーロードしなきゃいんじゃね?
  • 6. Item 27: Familiarize yourself with alternatives to overloading on universal references. これを template<typename T> void logAndAdd(T&& name); void logAndAdd(int idx);
  • 7. Item 27: Familiarize yourself with alternatives to overloading on universal references. これを template<typename T> void logAndAdd(T&& name); void logAndAdd(int idx); こうじゃ template<typename T> void logAndAddName(T&& name); void logAndAddNameIdx(int idx);
  • 8. Item 27: Familiarize yourself with alternatives to overloading on universal references. これを template<typename T> void logAndAdd(T&& name); void logAndAdd(int idx); こうじゃ template<typename T> void logAndAddName(T&& name); void logAndAddNameIdx(int idx); 全て解決!
  • 9. Item 27: Familiarize yourself with alternatives to overloading on universal references. 欠点 コンストラクタには無力 (コンストラクタには名前が無い) 本には名前固定って書いてあるけど、名前無いっすよ… §12[class.ctor]/p.1 "Constructors do not have names." てか、やっぱオーバーロード使いたくね?
  • 10. Item 27: Familiarize yourself with alternatives to overloading on universal references. 2.const T& で渡す そのまんま ユニバーサルリファレンス使うから訳がわからなくなる ⇓ ユニバーサルリファレンス使わなきゃいんじゃね?
  • 11. Item 27: Familiarize yourself with alternatives to overloading on universal references. これを template<typename T> void logAndAdd(T&& name); void logAndAdd(int idx);
  • 12. Item 27: Familiarize yourself with alternatives to overloading on universal references. これを template<typename T> void logAndAdd(T&& name); void logAndAdd(int idx); こうじゃ void logAndAdd(const std::string& name); void logAndAdd(int idx);
  • 13. Item 27: Familiarize yourself with alternatives to overloading on universal references. これを template<typename T> void logAndAdd(T&& name); void logAndAdd(int idx); こうじゃ void logAndAdd(const std::string& name); void logAndAdd(int idx); 全て解決!
  • 14. Item 27: Familiarize yourself with alternatives to overloading on universal references. 欠点 ユニバーサルリファレンス使う方法ほど 効率的じゃない (でもシンプルさは魅力的) てか、やっぱユニバーサルリファレンス 使いたくね?
  • 15. Item 27: Familiarize yourself with alternatives to overloading on universal references. 3.値で渡す そのまんま …え?効率は? 実はわりと効率がいい(場合も多い) けど、詳細は Item 41 のお楽しみ
  • 16. Item 27: Familiarize yourself with alternatives to overloading on universal references. これを template<typename T> explicit Person(T&& n) : name(std::forward<T>(n)) {} explicit Person(int idx) : name(nameFromIdx(idx)) {}
  • 17. Item 27: Familiarize yourself with alternatives to overloading on universal references. これを template<typename T> explicit Person(T&& n) : name(std::forward<T>(n)) {} explicit Person(int idx) : name(nameFromIdx(idx)) {} こうじゃ explicit Person(std::string n) : name(std::move(n)) {} explicit Perosn(int idx) : name(nameFromIdx(idx)) {}
  • 18. Item 27: Familiarize yourself with alternatives to overloading on universal references. これを template<typename T> explicit Person(T&& n) : name(std::forward<T>(n)) {} explicit Person(int idx) : name(nameFromIdx(idx)) {} こうじゃ explicit Person(std::string n) : name(std::move(n)) {} explicit Perosn(int idx) : name(nameFromIdx(idx)) {} 全て解決!
  • 19. Item 27: Familiarize yourself with alternatives to overloading on universal references. 欠点 この例ならわりと効率いいけど、 ユニバーサルリファレンスほどじゃないし、 ムーブが効率悪い場合には使えない。(std::array とか…) Item 41 を知らない人が見ると、「効率悪い!」と言われて、 最悪直される(※ 個人の感想です) 0 はともかく、NULL を渡すと int バージョン呼ばれる。 (けど、これに限らないし、Item 8 読め)
  • 20. Item 27: Familiarize yourself with alternatives to overloading on universal references. 4.タグディスパッチを使う やっぱ完全転送したい!!! ⇓ みんな大好き、タグディスパッチ
  • 21. Item 27: Familiarize yourself with alternatives to overloading on universal references. わ あ い タ グ デ ィ ス パ ッ チ め う め う タ グ デ ィ ス パ ッ チ 大 好 き め う ©芽兎めう
  • 22. Item 27: Familiarize yourself with alternatives to overloading on universal references. ユニバーサルリファレンスの問題点 あらゆる引数に完全一致する
  • 23. Item 27: Familiarize yourself with alternatives to overloading on universal references. 引 数 が 一 つ し か な い と 錯 覚 し て い た ? ©藍染惣右介
  • 24. Item 27: Familiarize yourself with alternatives to overloading on universal references. 解決策 ユニバーサルリファレンス以外 の引数で、オーバーロード解決 を制御すれば良い
  • 25. Item 27: Familiarize yourself with alternatives to overloading on universal references. 元のコード std::multiset<std::string> names; template<typename T> void logAndAdd(T&& name) { auto now = std::chrono::system_clock::now(); log(now, "logAndAdd"); names.emplace(std::forward<T>(name)); } これに、int を取るオーバーロードを追加したい
  • 26. Item 27: Familiarize yourself with alternatives to overloading on universal references. logAndAdd のオーバーロードを追加するんじゃなくて、 logAndAdd 内で実際に処理する関数 logAndAddImpl に処理を委譲する ⇓ この際、T が int の場合用と そうじゃない場合用の関数を作って それらの関数に追加の引数を追加して、 それらの型(タグ)が完璧に異なれば良い
  • 27. Item 27: Familiarize yourself with alternatives to overloading on universal references. クライアントが呼び出す関数 template<typename T> void logAndAdd(T&& name) { logAndAddImpl(name, 型①か型②); } 実際に処理する関数 void logAndAddImpl(T&& name, 型①) { int 以外の時の処理がここに } void logAndAddImpl(int idx, 型②) { int の時の処理がここに }T が int の以外時は「型①」 T が int の時は「型②」 つまり、こんな感じにすれば良い
  • 28. Item 27: Familiarize yourself with alternatives to overloading on universal references. クライアントが呼び出す関数 template<typename T> void logAndAdd(T&& name) { logAndAddImpl(name, 型①か型②); } 実際に処理する関数 void logAndAddImpl(T&& name, 型①) { int 以外の時の処理がここに } void logAndAddImpl(int idx, 型②) { int の時の処理がここに }T が int の以外時は「型①」 T が int の時は「型②」 つまり、こんな感じにすれば良い で? 「型①か型②」って?
  • 29. Item 27: Familiarize yourself with alternatives to overloading on universal references. これが「型①か型②」だ!!! template<typename T> void logAndAdd(T&& name) { logAndAddImpl(std::forward<T>(name), std::is_integral<T>()); } 引数だから、() を付 けてオブジェクト生成 T が int 以外の時は「std::false_type」から派生 T が int の時は「std::true_type」から派生
  • 30. Item 27: Familiarize yourself with alternatives to overloading on universal references. これが「型①か型②」だ!!! template<typename T> void logAndAdd(T&& name) { logAndAddImpl(std::forward<T>(name), std::is_integral<T>()); } 引数だから、() を付 けてオブジェクト生成 T が int 以外の時は「std::false_type」から派生 T が int の時は「std::true_type」から派生 でもちょっと うまくない…
  • 31. Item 27: Familiarize yourself with alternatives to overloading on universal references. int i = 10; … logAndAdd(i); template<typename T> void logAndAdd(T&& name) { logAndAddImpl( std::forward<T>(name), std::is_integral<T>()); } うまくない理由 こんな感じで呼び出すと… T が int& になっちゃう ⇒参照型は整数型じゃないから、 std::false_typeになっちゃう
  • 32. Item 27: Familiarize yourself with alternatives to overloading on universal references. これが正しい「型①か型②」だ!!! template<typename T> void logAndAdd(T&& name) { logAndAddImpl( std::forward<T>(name), std::is_integral<typename std::remove_reference<T>::type>()); } T が int っぽくない時は「std::false_type」 T が int っぽい時は「std::true_type」 T から「参照」を消す
  • 33. Item 27: Familiarize yourself with alternatives to overloading on universal references. ちな、処理本体側はこんな感じ // int 以外用の関数 template<typename T> void logAndAddImpl(T&& name, std::false_type) { auto now = std::chrono::system_clock::now(); log(now, "logAndAdd"); names.emplace(std::forward<T>(name)); } std::string nameFromIdx(int idx); // int 用の関数 void logAndAddImpl(int idx, std::true_type) { logAndAdd(nameFromIdx(idx)); } オーバーロード解決の ためだけにあるから、 パラメータ名は 付けてない オーバーロード解決の ためだけにあるから、 パラメータ名は 付けてない idx から名前に 変換したら、 再度 logAndAdd を 呼び出す
  • 34. Item 27: Familiarize yourself with alternatives to overloading on universal references. ちな、処理本体側はこんな感じ // int 以外用の関数 template<typename T> void logAndAddImpl(T&& name, std::false_type) { auto now = std::chrono::system_clock::now(); log(now, "logAndAdd"); names.emplace(std::forward<T>(name)); } std::string nameFromIdx(int idx); // int 用の関数 void logAndAddImpl(int idx, std::true_type) { logAndAdd(nameFromIdx(idx)); } オーバーロード解決の ためだけにあるから、 パラメータ名は 付けてない オーバーロード解決の ためだけにあるから、 パラメータ名は 付けてない idx から名前に 変換したら、 再度 logAndAdd を 呼び出す 賢いコンパイラなら、 最後のパラメータ使ってないから 消してくれるかも… こうすれば、ログ出力コード 二重にメンテしなくて済む…
  • 35. Item 27: Familiarize yourself with alternatives to overloading on universal references. タグディスパッチSUGEEEE!!!! タグディスパッチのこと もっと知りたい!!! でも EMC++ にはそこまで書かれてない…
  • 36. Item 27: Familiarize yourself with alternatives to overloading on universal references. そんなあなたに C++テンプレートテクニック 第2版 あのえぴさんと アキラさんが 書いてるぞ!!! C++11 完全対応!!! 電子書籍版も あるぞ!!! ちょっと読みづらいけど… タグディスパッチ だけじゃなくて テンプレート 全般!!! まだ全部理解できてないけど…
  • 37. Item 27: Familiarize yourself with alternatives to overloading on universal references. タグディスパッチいいよ、タグディスパッチ もう何もかもタグディスパッチでよくね?
  • 38. Item 27: Familiarize yourself with alternatives to overloading on universal references. 欠点 コンストラクタには無力 (またっすか…)
  • 39. Item 27: Familiarize yourself with alternatives to overloading on universal references. 例のダメなクラス class Person { public: template<typename T> explicit Person(T&& n) : name(std::forward<Person&>(n)) {} explicit Person(int idx); Person(const Person& rhs); Person(Person&& rhs); … }; 完全転送 コンストラクタ int コンストラクタ コピー コンストラクタ ムーブ コンストラクタ
  • 40. Item 27: Familiarize yourself with alternatives to overloading on universal references. 例のダメなクラス class Person { public: template<typename T> explicit Person(T&& n) : name(std::forward<Person&>(n)) {} explicit Person(int idx); Person(const Person& rhs); Person(Person&& rhs); … }; Person p("Nancy"); auto cloneOfP(p); 全部完全転送… 上はいいけど、下に対して コピーコンストラクタが 呼ばれない…
  • 41. Item 27: Familiarize yourself with alternatives to overloading on universal references. 5.ユニバーサルリファレンスをとるテンプレートに制約を設ける そのまんま ユニバーサルリファレンスを取る関数が 呼ばれて欲しくない時まで呼ばれちゃう ⇓ 関数を呼ばれて欲しい時だけ 有効にすればいんじゃね?
  • 42. Item 27: Familiarize yourself with alternatives to overloading on universal references. 「関数を呼ばれて欲しい時だけ有効に」? そのためのメタ関数が type_traits に! std::enable_if SFINAE と呼ばれる 機構を使ってる
  • 43. Item 27: Familiarize yourself with alternatives to overloading on universal references. 使い方はこんな感じ class Person { public: template<typename T, typename = typename std::enable_if<condition>::type> explicit Person(T&& n); … }; この condition の部分に、このコンストラク タを使っても良い条件式を書く。 ただし、コンパイル時定数のみ!! 関数テンプレートのデフォルトテンプレート引数 (C++11の新機能!)を enable_if にする
  • 44. Item 27: Familiarize yourself with alternatives to overloading on universal references. では、今回の場合、どんな時に呼ばれて欲しいのか? ⇓ T が Person じゃない時 T が Person の場合、コピーコンストラクタや ムーブコンストラクタが呼ばれて欲しいから そんな時も type_traits
  • 45. Item 27: Familiarize yourself with alternatives to overloading on universal references. こんな式 !std::is_same<Person, T>::value 先頭の!に注意 Person と T が 同じ型の時 true 型じゃなくて bool 値が欲しいから ::value
  • 46. Item 27: Familiarize yourself with alternatives to overloading on universal references. class Person { public: template< typename T, typename = typename std::enable_if< !std::is_same<Person, T>::value >::type > explicit Person(T&& n); Person(const Person&); Person(Person&&); … }; ダメでした… Person p("Nancy"); auto cloneOfP(p); T は const char(&)[6] T は Person& p は左辺値だから T が左辺値参照に…
  • 47. Item 27: Familiarize yourself with alternatives to overloading on universal references. T と Person を比較する時には、以下の2点を無視したい • 参照かどうか 引数の型が Person だろうが Person& だろうが Person&& だろうが、 完全転送コンストラクタじゃ無くてコピー・ムーブコンストラクタが呼ばれてほしい • const や volatile が付いているかどうか 引数の型が const Person だろうが volatile Person だろうが const volatile Person だろうが、完全転送コンストラクタじゃ無k(以下略 そんな時も type_traits
  • 48. Item 27: Familiarize yourself with alternatives to overloading on universal references. こんな式 !std::is_same<Person, typename std::decay<T>::type >::value ホントはこれだと、配列や関数をポインタに変換しちゃうけど、今回の場合は問題なし 参照を取ってから、 更に cv 修飾を取る!! 値じゃなくて型が 欲しいから ::type
  • 49. Item 27: Familiarize yourself with alternatives to overloading on universal references. class Person { public: template< typename T, typename = typename std::enable_if< !std::is_same< Person, typename std::decay<T>::type >::value >::type > explicit Person(T&& n); Person(const Person&); Person(Person&&); … }; まだダメでした… class SP : public Person { public: SP(const SP& rhs) : Person(rhs) { … } SP(SP&& rhs) : Person(std::move(rhs)) { … } … }; T は const SP& T は SP&&
  • 50. Item 27: Familiarize yourself with alternatives to overloading on universal references. 完全転送コンストラクタは、 T が Person かその派生クラスの時には 無効化されて欲しい そんな時も type_traits
  • 51. Item 27: Familiarize yourself with alternatives to overloading on universal references. class Person { public: template< typename T, typename = typename std::enable_if< !std::is_base_of<Person, typename std::decay<T>::type >::value >::type > explicit Person(T&& n); … }; typename std::decay<T>::type が Person の派生クラスの時 true Person そのものでもOK! だいぶ長い…
  • 52. Item 27: Familiarize yourself with alternatives to overloading on universal references. class Person { public: template< typename T, typename = typename std::enable_if< !std::is_base_of<Person, typename std::decay<T>::type >::value >::type > explicit Person(T&& n); … }; typename std::decay<T>::type が Person の派生クラスの時 true Person そのものでもOK! だいぶ長い… Errata に補足あり! std::is_base_of<int, int> は false になるよ!
  • 53. Item 27: Familiarize yourself with alternatives to overloading on universal references. class Person { public: template< typename T, typename = std::enable_if_t< !std::is_base_of<Person, std::decay_t<T> >::value > > explicit Person(T&& n); … }; ちなみに C++14 だったら もうちょっとスマート(かな?) typename と ::type が 必要ない! C++14 でも ::value は必要 (大人の事情により _v は入らず…)
  • 54. Item 27: Familiarize yourself with alternatives to overloading on universal references. でもまだ int を引数にとる コンストラクタが追加されてない…
  • 55. Item 27: Familiarize yourself with alternatives to overloading on universal references. class Person { public: template<typename T, typename = std::enable_if_t< !std::is_base_of<Person, std::decay_t<T>>::value && !std::is_integral<std::remove_reference_t<T>>::value > > explicit Person(T&& n) : name(std::forward<T>(n)) { … } explicit Person(int idx) : name(nameFromIdx(idx)) { … } … private: std::string name; }; C++14 でも 超絶長い…
  • 56. Item 27: Familiarize yourself with alternatives to overloading on universal references. SFINAE SUGEEEE!!!! SFINAEのこと もっと知りたい!!! でも EMC++ にはそこまで書かれてない…
  • 57. Item 27: Familiarize yourself with alternatives to overloading on universal references. そんなあなたに C++テンプレートテクニック 第2版 あのえぴさんと アキラさんが 書いてるぞ!!! C++11 完全対応!!! 電子書籍版も あるぞ!!! ちょっと読みづらいけど… SFINAE だけじゃなくて テンプレート 全般!!! まだ全部理解できてないけど…
  • 58. Item 27: Familiarize yourself with alternatives to overloading on universal references. トレードオフ 1. オーバーロードを諦める 2. const T& で渡す 3. 値で渡す 4. タグディスパッチを使う 5. ユニバーサルリファレンスをとる テンプレートに制約を設ける 完全転送を 諦める (シンプル) 完全転送を 使う (効率いい)
  • 59. Item 27: Familiarize yourself with alternatives to overloading on universal references. 完全転送の欠点 1.完全転送できない場合がある (完全じゃね~し… Item 30を参照) 2.クライアントが誤った引数を渡した時、 とち狂ったエラーメッセージが出る
  • 60. Item 27: Familiarize yourself with alternatives to overloading on universal references. とち狂ったメッセージの例 例えば、こんな感じに間違った場合… Person p(u"Konrad Zuse"); 巷で話題の utf-16 リテラル
  • 61. Item 27: Familiarize yourself with alternatives to overloading on universal references. prog.cc: In instantiation of 'Person::Person(T&&) [with T = const char32_t (&)[5]; <template-parameter-1-2> = void]': prog.cc:30:18: required from here prog.cc:16:27: error: no matching function for call to 'std::__cxx11::basic_string<char>::basic_string(const char32_t [5])' : name(std::forward<T>(n)) ^ In file included from /usr/local/gcc-head/include/c++/6.0.0/string:52:0, from prog.cc:2: /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:535:9: note: candidate: template<class _InputIterator, class> std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(_InputIterator, _InputIterator, const _Alloc&) basic_string(_InputIterator __beg, _InputIterator __end, ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:535:9: note: template argument deduction/substitution failed: prog.cc:16:27: note: candidate expects 3 arguments, 1 provided : name(std::forward<T>(n)) ^ In file included from /usr/local/gcc-head/include/c++/6.0.0/string:52:0, from prog.cc:2: /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:512:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&&, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>] basic_string(basic_string&& __str, const _Alloc& __a) ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:512:7: note: candidate expects 2 arguments, 1 provided /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:508:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>] basic_string(const basic_string& __str, const _Alloc& __a) ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:508:7: note: candidate expects 2 arguments, 1 provided /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:504:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::initializer_list<_Tp>, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>] basic_string(initializer_list<_CharT> __l, const _Alloc& __a = _Alloc()) ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:504:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'std::initializer_list<char>' /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:477:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>] basic_string(basic_string&& __str) noexcept ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:477:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'std::__cxx11::basic_string<char>&&' /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:465:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type, _CharT, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int] basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc()) ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:465:7: note: candidate expects 3 arguments, 1 provided /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:455:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>] basic_string(const _CharT* __s, const _Alloc& __a = _Alloc()) ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:455:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'const char*' /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:445:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int] basic_string(const _CharT* __s, size_type __n, ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:445:7: note: candidate expects 3 arguments, 1 provided /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:427:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int] basic_string(const basic_string& __str, size_type __pos, ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:427:7: note: candidate expects 4 arguments, 1 provided /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:411:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int] basic_string(const basic_string& __str, size_type __pos, ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:411:7: note: candidate expects 3 arguments, 1 provided /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:399:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>] basic_string(const basic_string& __str) ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:399:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'const std::__cxx11::basic_string<char>&' /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:391:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>] basic_string(const _Alloc& __a) ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:391:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'const std::allocator<char>&' /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:380:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string() [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>] basic_string() ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:380:7: note: candidate expects 0 arguments, 1 provided GCC さん
  • 62. Item 27: Familiarize yourself with alternatives to overloading on universal references. prog.cc:16:4: error: no matching constructor for initialization of 'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >') : name(std::forward<T>(n)) ^ ~~~~~~~~~~~~~~~~~~ prog.cc:30:9: note: in instantiation of function template specialization 'Person::Person<char32_t const (&)[5], void>' requested here Person p(U"name"); ^ /usr/local/libcxx-head/include/c++/v1/string:1326:40: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'const allocator_type' (aka 'const std::__1::allocator<char>') for 1st argument _LIBCPP_INLINE_VISIBILITY explicit basic_string(const allocator_type& __a) ^ /usr/local/libcxx-head/include/c++/v1/string:1333:5: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'const std::__1::basic_string<char>' for 1st argument basic_string(const basic_string& __str); ^ /usr/local/libcxx-head/include/c++/v1/string:1338:5: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'std::__1::basic_string<char>' for 1st argument basic_string(basic_string&& __str) ^ /usr/local/libcxx-head/include/c++/v1/string:1348:31: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'const value_type *' (aka 'const char *') for 1st argument _LIBCPP_INLINE_VISIBILITY basic_string(const value_type* __s); ^ /usr/local/libcxx-head/include/c++/v1/string:1369:5: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'initializer_list<value_type>' for 1st argument basic_string(initializer_list<value_type> __il); ^ /usr/local/libcxx-head/include/c++/v1/string:1363:9: note: candidate constructor template not viable: requires 2 arguments, but 1 was provided basic_string(_InputIterator __first, _InputIterator __last); ^ /usr/local/libcxx-head/include/c++/v1/string:1366:9: note: candidate constructor template not viable: requires 3 arguments, but 1 was provided basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a); ^ /usr/local/libcxx-head/include/c++/v1/string:1323:31: note: candidate constructor not viable: requires 0 arguments, but 1 was provided _LIBCPP_INLINE_VISIBILITY basic_string() ^ /usr/local/libcxx-head/include/c++/v1/string:1346:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided basic_string(basic_string&& __str, const allocator_type& __a); ^ /usr/local/libcxx-head/include/c++/v1/string:1334:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided basic_string(const basic_string& __str, const allocator_type& __a); ^ /usr/local/libcxx-head/include/c++/v1/string:1350:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided basic_string(const value_type* __s, const allocator_type& __a); ^ /usr/local/libcxx-head/include/c++/v1/string:1352:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided basic_string(const value_type* __s, size_type __n); ^ /usr/local/libcxx-head/include/c++/v1/string:1356:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided basic_string(size_type __n, value_type __c); ^ /usr/local/libcxx-head/include/c++/v1/string:1371:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided basic_string(initializer_list<value_type> __il, const allocator_type& __a); ^ /usr/local/libcxx-head/include/c++/v1/string:1354:5: note: candidate constructor not viable: requires 3 arguments, but 1 was provided basic_string(const value_type* __s, size_type __n, const allocator_type& __a); ^ /usr/local/libcxx-head/include/c++/v1/string:1358:5: note: candidate constructor not viable: requires 3 arguments, but 1 was provided basic_string(size_type __n, value_type __c, const allocator_type& __a); ^ /usr/local/libcxx-head/include/c++/v1/string:1359:5: note: candidate constructor not viable: requires at least 2 arguments, but 1 was provided basic_string(const basic_string& __str, size_type __pos, size_type __n = npos, ^ Clang さん
  • 63. Item 27: Familiarize yourself with alternatives to overloading on universal references. この例の場合、 ユニバーサルリファレンスの引数は std::string の初期化に使われることが 分かっているので、 static_assert でチェックすることはできる。
  • 64. Item 27: Familiarize yourself with alternatives to overloading on universal references. class Person { public: template<typename T, typename = std::enable_if_t< !std::is_base_of<Person, std::decay_t<T>>::value && !std::is_integral<std::remove_reference_t<T>>::value > > explicit Person(T&& n) : name(std::forward<T>(n)) { // assert that a std::string can be created from a T object static_assert( std::is_constructible<std::string, T>::value, "Parameter n can't be used to construct a std::string" ); … } … }; こんな感じでチェック!
  • 65. Item 27: Familiarize yourself with alternatives to overloading on universal references. prog.cc: In instantiation of 'Person::Person(T&&) [with T = const char32_t (&)[5]; <template-parameter-1-2> = void]': prog.cc:35:18: required from here prog.cc:16:27: error: no matching function for call to 'std::__cxx11::basic_string<char>::basic_string(const char32_t [5])' : name(std::forward<T>(n)) ^ In file included from /usr/local/gcc-head/include/c++/6.0.0/string:52:0, from prog.cc:2: /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:535:9: note: candidate: template<class _InputIterator, class> std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(_InputIterator, _InputIterator, const _Alloc&) basic_string(_InputIterator __beg, _InputIterator __end, ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:535:9: note: template argument deduction/substitution failed: prog.cc:16:27: note: candidate expects 3 arguments, 1 provided : name(std::forward<T>(n)) ^ In file included from /usr/local/gcc-head/include/c++/6.0.0/string:52:0, from prog.cc:2: /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:512:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&&, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>] basic_string(basic_string&& __str, const _Alloc& __a) ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:512:7: note: candidate expects 2 arguments, 1 provided /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:508:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>] basic_string(const basic_string& __str, const _Alloc& __a) ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:508:7: note: candidate expects 2 arguments, 1 provided /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:504:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::initializer_list<_Tp>, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>] basic_string(initializer_list<_CharT> __l, const _Alloc& __a = _Alloc()) ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:504:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'std::initializer_list<char>' /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:477:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>] basic_string(basic_string&& __str) noexcept ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:477:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'std::__cxx11::basic_string<char>&&' /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:465:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type, _CharT, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int] basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc()) ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:465:7: note: candidate expects 3 arguments, 1 provided /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:455:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>] basic_string(const _CharT* __s, const _Alloc& __a = _Alloc()) ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:455:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'const char*' /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:445:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int] basic_string(const _CharT* __s, size_type __n, ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:445:7: note: candidate expects 3 arguments, 1 provided /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:427:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int] basic_string(const basic_string& __str, size_type __pos, ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:427:7: note: candidate expects 4 arguments, 1 provided /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:411:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int] basic_string(const basic_string& __str, size_type __pos, ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:411:7: note: candidate expects 3 arguments, 1 provided /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:399:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>] basic_string(const basic_string& __str) ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:399:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'const std::__cxx11::basic_string<char>&' /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:391:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>] basic_string(const _Alloc& __a) ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:391:7: note: no known conversion for argument 1 from 'const char32_t [5]' to 'const std::allocator<char>&' /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:380:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string() [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>] basic_string() ^ /usr/local/gcc-head/include/c++/6.0.0/bits/basic_string.h:380:7: note: candidate expects 0 arguments, 1 provided prog.cc:19:3: error: static assertion failed: Parameter n can't be used to construct a std::string static_assert( ^ GCC さん ここ!
  • 66. Item 27: Familiarize yourself with alternatives to overloading on universal references. prog.cc:16:4: error: no matching constructor for initialization of 'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >') : name(std::forward<T>(n)) ^ ~~~~~~~~~~~~~~~~~~ prog.cc:35:9: note: in instantiation of function template specialization 'Person::Person<char32_t const (&)[5], void>' requested here Person p(U"name"); ^ /usr/local/libcxx-head/include/c++/v1/string:1326:40: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'const allocator_type' (aka 'const std::__1::allocator<char>') for 1st argument _LIBCPP_INLINE_VISIBILITY explicit basic_string(const allocator_type& __a) ^ /usr/local/libcxx-head/include/c++/v1/string:1333:5: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'const std::__1::basic_string<char>' for 1st argument basic_string(const basic_string& __str); ^ /usr/local/libcxx-head/include/c++/v1/string:1338:5: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'std::__1::basic_string<char>' for 1st argument basic_string(basic_string&& __str) ^ /usr/local/libcxx-head/include/c++/v1/string:1348:31: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'const value_type *' (aka 'const char *') for 1st argument _LIBCPP_INLINE_VISIBILITY basic_string(const value_type* __s); ^ /usr/local/libcxx-head/include/c++/v1/string:1369:5: note: candidate constructor not viable: no known conversion from 'char32_t const[5]' to 'initializer_list<value_type>' for 1st argument basic_string(initializer_list<value_type> __il); ^ /usr/local/libcxx-head/include/c++/v1/string:1363:9: note: candidate constructor template not viable: requires 2 arguments, but 1 was provided basic_string(_InputIterator __first, _InputIterator __last); ^ /usr/local/libcxx-head/include/c++/v1/string:1366:9: note: candidate constructor template not viable: requires 3 arguments, but 1 was provided basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a); ^ /usr/local/libcxx-head/include/c++/v1/string:1323:31: note: candidate constructor not viable: requires 0 arguments, but 1 was provided _LIBCPP_INLINE_VISIBILITY basic_string() ^ /usr/local/libcxx-head/include/c++/v1/string:1346:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided basic_string(basic_string&& __str, const allocator_type& __a); ^ /usr/local/libcxx-head/include/c++/v1/string:1334:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided basic_string(const basic_string& __str, const allocator_type& __a); ^ /usr/local/libcxx-head/include/c++/v1/string:1350:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided basic_string(const value_type* __s, const allocator_type& __a); ^ /usr/local/libcxx-head/include/c++/v1/string:1352:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided basic_string(const value_type* __s, size_type __n); ^ /usr/local/libcxx-head/include/c++/v1/string:1356:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided basic_string(size_type __n, value_type __c); ^ /usr/local/libcxx-head/include/c++/v1/string:1371:5: note: candidate constructor not viable: requires 2 arguments, but 1 was provided basic_string(initializer_list<value_type> __il, const allocator_type& __a); ^ /usr/local/libcxx-head/include/c++/v1/string:1354:5: note: candidate constructor not viable: requires 3 arguments, but 1 was provided basic_string(const value_type* __s, size_type __n, const allocator_type& __a); ^ /usr/local/libcxx-head/include/c++/v1/string:1358:5: note: candidate constructor not viable: requires 3 arguments, but 1 was provided basic_string(size_type __n, value_type __c, const allocator_type& __a); ^ /usr/local/libcxx-head/include/c++/v1/string:1359:5: note: candidate constructor not viable: requires at least 2 arguments, but 1 was provided basic_string(const basic_string& __str, size_type __pos, size_type __n = npos, ^ prog.cc:19:3: error: static_assert failed "Parameter n can't be used to construct a std::string" static_assert( ^ Clang さん ここ!
  • 67. Item 27: Familiarize yourself with alternatives to overloading on universal references. でも、今回の例の場合、 ホントはそもそも std::enable_if の条件に std::is_constructible 使えばいいと 思うんだけど… Errata には、コンパイラのエラーメッセージが、 「そんなコンストラクタ無いよ」ってなるので、 意味が変わっちゃうって書いてあるけど…
  • 68. Item 27: Familiarize yourself with alternatives to overloading on universal references. こんな感じ class Person { public: template<typename T, typename = std::enable_if_t<std::is_constructible<std::string, T>::value> > explicit Person(T&& n) : name(std::forward<T>(n)) { … } … }; こんな感じで無効化!
  • 69. Item 27: Familiarize yourself with alternatives to overloading on universal references. prog.cc: In function 'int main()': prog.cc:26:18: error: no matching function for call to 'Person::Person(const char32_t [5])' Person p(U"name"); ^ prog.cc:18:2: note: candidate: Person::Person(Person&&) Person(Person&&) = default; ^ prog.cc:18:2: note: no known conversion for argument 1 from 'const char32_t [5]' to 'Person&&' prog.cc:17:2: note: candidate: Person::Person(const Person&) Person(const Person&) = default; ^ prog.cc:17:2: note: no known conversion for argument 1 from 'const char32_t [5]' to 'const Person&' prog.cc:11:11: note: candidate: template<class T, class> Person::Person(T&&) explicit Person(T&& n) ^ prog.cc:11:11: note: template argument deduction/substitution failed: GCC さん
  • 70. Item 27: Familiarize yourself with alternatives to overloading on universal references. prog.cc:26:9: error: no matching constructor for initialization of 'Person' Person p(U"name"); ^ ~~~~~~~ prog.cc:17:2: note: candidate constructor not viable: no known conversion from 'const char32_t [5]' to 'const Person' for 1st argument Person(const Person&) = default; ^ prog.cc:18:2: note: candidate constructor not viable: no known conversion from 'const char32_t [5]' to 'Person' for 1st argument Person(Person&&) = default; ^ /usr/local/libcxx-head/include/c++/v1/type_traits:244:78: note: candidate template ignored: disabled by 'enable_if' [with T = char32_t const (&)[5]] template <bool _Bp, class _Tp = void> using enable_if_t = typename enable_if<_Bp, _Tp>::type; ^ Clang さん Clang さんすごい!
  • 71. Item 27: Familiarize yourself with alternatives to overloading on universal references. 覚えておくこと • ユニバーサルリファレンスとオーバーロードの組み合わせの代替案 には、異なる関数名を使用する、パラメータをconstへの左辺値参 照で渡す、パラメータを値で渡す、タグディスパッチを使う、が含まれ る。 • std::enable_if を通じてテンプレートを制約することで、ユニ バーサルリファレンスとオーバーロードを同時に使用できるが、それ はコンパイラがユニバーサルリファレンスのオーバーロードを使用す る条件を制御する。 • ユニバーサルリファレンスはたいてい効率上の利点があるが、概し て使い勝手の点で欠点もある。