प्रेरणा खुद को कागज में देखा जा सकता है ।
कंस्ट्रक्टरों को सशर्त रूप से स्पष्ट करने की आवश्यकता है। यानी आप चाहते हैं:
pair<string, string> safe() {
return {"meow", "purr"}; // ok
}
pair<vector<int>, vector<int>> unsafe() {
return {11, 22}; // error
}
पूर्व ठीक है, जो निर्माणकर्ता निहित हैं। लेकिन उत्तरार्द्ध बुरा होगा, वे निर्माता हैं explicit। C ++ 17 (या अवधारणाओं के साथ C ++ 20) के साथ, इस काम को करने का एकमात्र तरीका दो निर्माणकर्ताओं को लिखना है - एक explicitऔर एक:
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&& );
};
ये लगभग पूरी तरह से डुप्लिकेट हैं - और इन निर्माणकर्ताओं की परिभाषाएं समान होंगी।
के साथ explicit(bool), आप बस एक ही कंस्ट्रक्टर लिख सकते हैं - निर्माण के सशर्त रूप से स्पष्ट भाग के साथ स्थानीयकृत 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&& );
};
यह बेहतर तरीके से मेल खाता है, लिखने के लिए बहुत कम कोड है, और ओवरलोड रिज़ॉल्यूशन के दौरान कंपाइलर के लिए कम काम है (क्योंकि बीच में लेने के लिए कम कंस्ट्रक्टर होने चाहिए)।
tupleइस सुविधा के साथ उन जैसे सशर्त रूप से स्पष्ट निर्माणकर्ताओं को लागू करना बहुत आसान हो जाता है ।