Motivasyonun kendisi makalede görülebilir .
Yapıcıları koşullu olarak açık hale getirmeye ihtiyaç vardır. Yani, istediğiniz:
pair<string, string> safe() {
return {"meow", "purr"}; // ok
}
pair<vector<int>, vector<int>> unsafe() {
return {11, 22}; // error
}
Birincisi iyi, bu yapıcılar örtük. Ama ikincisi kötü olurdu, bu yapıcılar explicit
. C ++ 17 (veya kavramları olan C ++ 20) ile, bu işi yapmanın tek yolu iki yapıcı yazmaktır - explicit
biri değil biri:
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&& );
};
Bunlar neredeyse tamamen kopyalanmıştır ve bu kurucuların tanımları aynı olacaktır.
İle explicit(bool)
, yalnızca tek bir kurucu yazabilirsiniz - yapının koşullu olarak açık kısmı sadece explicit
-specifier için yerelleştirilmiştir :
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&& );
};
Bu amaç ile daha iyi eşleşir, yazmak için daha az koddur ve aşırı yük çözünürlüğü sırasında derleyicinin yapması için daha az iştir (çünkü aralarından seçim yapmak için daha az kurucu olduğundan).
tuple
bu özelliğe sahip olanlar gibi koşullu olarak açık kurucuları uygulamak çok daha kolay hale geliyor .