Motivasi itu sendiri dapat dilihat di koran .
Ada kebutuhan untuk membuat konstruktor eksplisit secara kondisional. Anda ingin:
pair<string, string> safe() {
return {"meow", "purr"}; // ok
}
pair<vector<int>, vector<int>> unsafe() {
return {11, 22}; // error
}
Yang pertama baik-baik saja, konstruktor itu implisit. Tapi yang terakhir akan buruk, konstruktor itu explicit
. Dengan C ++ 17 (atau C ++ 20 dengan konsep), satu-satunya cara untuk membuat karya ini adalah dengan menulis dua konstruktor - satu explicit
dan satu tidak:
template <typename T1, typename T2>
struct pair {
template <typename U1=T1, typename U2=T2,
std::enable_if_t<
std::is_constructible_v<T1, U1> &&
std::is_constructible_v<T2, U2> &&
std::is_convertible_v<U1, T1> &&
std::is_convertible_v<U2, T2>
, int> = 0>
constexpr pair(U1&&, U2&& );
template <typename U1=T1, typename U2=T2,
std::enable_if_t<
std::is_constructible_v<T1, U1> &&
std::is_constructible_v<T2, U2> &&
!(std::is_convertible_v<U1, T1> &&
std::is_convertible_v<U2, T2>)
, int> = 0>
explicit constexpr pair(U1&&, U2&& );
};
Ini hampir seluruhnya digandakan - dan definisi konstruktor ini akan sama.
Dengan explicit(bool)
, Anda bisa menulis konstruktor tunggal - dengan bagian eksplisit kondisional dari konstruksi dilokalkan ke explicit
-specifier:
template <typename T1, typename T2>
struct pair {
template <typename U1=T1, typename U2=T2,
std::enable_if_t<
std::is_constructible_v<T1, U1> &&
std::is_constructible_v<T2, U2>
, int> = 0>
explicit(!std::is_convertible_v<U1, T1> ||
!std::is_convertible_v<U2, T2>)
constexpr pair(U1&&, U2&& );
};
Maksud kecocokan ini lebih baik, lebih sedikit kode untuk ditulis, dan lebih sedikit pekerjaan yang harus dilakukan oleh kompiler selama resolusi kelebihan (karena ada lebih sedikit konstruktor yang harus dipilih).
tuple
fitur ini.