Herb Sutter の基本に戻る! CppCon での Essentials of Modern C++プレゼンテーションでは、パラメーターを渡すためのさまざまなオプションについて説明し、それらのパフォーマンスと記述/教育の容易さを比較しました。「高度な」オプション (テストされたすべてのケースで最高のパフォーマンスを提供しますが、ほとんどの開発者が書くには難しすぎる) は、次の例で完全な転送でした(PDF、28 ページ) :
class employee {
std::string name_;
public:
template <class String,
class = std::enable_if_t<!std::is_same<std::decay_t<String>,
std::string>::value>>
void set_name(String &&name) noexcept(
std::is_nothrow_assignable<std::string &, String>::value) {
name_ = std::forward<String>(name);
}
};
この例では、テンプレート パラメーターString
をenable_if
. ただし、制約は正しくないようです。このメソッドは、String
型が astd::string
でない場合にのみ使用できると言っているようですが、意味がありません。つまり、このstd::string
メンバーは値以外を使用して設定できますstd::string
。
using namespace std::string_literals;
employee e;
e.set_name("Bob"s); // error
私が考えた 1 つの説明は、単純なタイプミスがあり、制約が のstd::is_same<std::decay_t<String>, std::string>::value
代わりになることを意図していたというものでし!std::is_same<std::decay_t<String>, std::string>::value
た。ただし、それはセッターが動作しないことを意味します。たとえば、const char *
プレゼンテーションでテストされたケースの 1 つであることを考えると、明らかにこの型で動作することを意図していました。
正しい制約は次のように思われます。
template <class String,
class = std::enable_if_t<std::is_assignable<decltype((name_)),
String>::value>>
void set_name(String &&name) noexcept(
std::is_nothrow_assignable<decltype((name_)), String>::value) {
name_ = std::forward<String>(name);
}
メンバーに割り当てることができるものはすべてセッターで使用できます。
適切な制約がありますか? 他に改善できる点はありますか?元の制約についての説明はありますか?おそらく文脈から外されたのでしょうか?
また、この宣言の複雑で「教えられない」部分が本当に有益なのだろうかと思います。オーバーロードを使用していないため、通常のテンプレートのインスタンス化に単純に依存できます。
template <class String>
void set_name(String &&name) noexcept(
std::is_nothrow_assignable<decltype((name_)), String>::value) {
name_ = std::forward<String>(name);
}
そしてもちろん、本当に重要かどうかについてはいくつかの議論がありnoexcept
、move/swap プリミティブを除いて、あまり気にする必要はないと言う人もいます:
template <class String>
void set_name(String &&name) {
name_ = std::forward<String>(name);
}
おそらく、概念があれば、単にエラー メッセージを改善するために、テンプレートを制約することは不当に難しくないでしょう。
template <class String>
requires std::is_assignable<decltype((name_)), String>::value
void set_name(String &&name) {
name_ = std::forward<String>(name);
}
これにはまだ仮想化できないという欠点と、ヘッダーになければならないという欠点がありますが (モジュールが最終的にその問題を解決することを願っています)、これはかなり教えられるようです。