my_fun SFINAE का उपयोग कर निम्नलिखित के रूप में लागू किया जा सकता।
namespace details{
struct A{};
struct B:A{};
// A container will have a begin and an end. Also make it first prerference
template<typename T>
auto my_fun_impl(T const & obj, B *) -> decltype(obj.begin(),obj.end(),void())
{
std::cout<<"Container\n";
}
// Default choice
template<typename T>
auto my_fun_impl(T const & obj,A*) -> void
{
std::cout<<"Other than Container\n";
}
}
template<typename T>
auto my_fun(T const & obj) -> void
{
details::my_fun_impl(obj,static_cast<details::B *>(0));
}
नोट एक Base
या Derived
वर्ग सूचक गुजर यहाँ, अन्यथा संकलक के बारे में अस्पष्ट समारोह परिभाषा में शिकायत करेंगे।
कंपाइलर my_fun_impl
के B pointer
के सटीक हस्ताक्षर से मिलान करने का प्रयास करेगा, यह कंटेनर के मामले में सफल होगा। क्योंकि एक कंटेनर शुरू होता है() और अंत(), पिछला रिटर्न प्रकार में अपेक्षित है।
गैर-कंटेनर प्रकार के मामले में पहला विकल्प मिलान करने में विफल रहेगा। और जैसा कि हम जानते हैं कि Base
क्लास पॉइंटर एक व्युत्पन्न क्लास ऑब्जेक्ट रख सकता है, इसलिए डिफ़ॉल्ट मिलान सफल हो जाएगा।
और परीक्षण कोड निम्न में से उत्पादन
int main()
{
my_fun(std::vector<int>{1,2,3});
my_fun(1);
}
एक बुरा डिजाइन की तरह लग रही इसके अलावा
Container
Other than Container
Demo on coliru
हो जाएगा और मुझे सिफारिश कर आप के बजाय डिजाइन पर देखें, तो आप इस्तेमाल कर सकते हैं [ * प्रकार- लक्षण *] (http://en.cppreference.com/w/cpp/types#Type_traits_.28since_C.2B.2B11.29)। आपको विशिष्ट प्रकार-लक्षणों को लागू करने की आवश्यकता हो सकती है जो आपको उपयुक्त हैं, जैसे 'is_container'। –
'std :: string' निश्चित रूप से वर्णों का एक कंटेनर है, इसलिए यह प्रश्न एक झूठी डिचोटोमी मानता है। – MSalters