चूंकि आपने कहा था कि आप अभी भी एक बेहतर उत्तर की प्रतीक्षा कर रहे थे, यहां पर मेरा ध्यान है। यह सही नहीं है, लेकिन मुझे लगता है कि यह आपको SFINAE और आंशिक विशेषज्ञता का उपयोग करके यथासंभव संभव बनाता है। (मुझे लगता है कि अवधारणाएं एक पूर्ण और सुरुचिपूर्ण समाधान प्रदान करेंगी, लेकिन हमें इसके लिए थोड़ी देर इंतजार करना होगा।)
समाधान उपनाम टेम्पलेट्स की एक विशेषता पर निर्भर करता है जो मानक कामकाजी ड्राफ्ट में हाल ही में निर्दिष्ट किया गया था सी ++ 14 के अंतिम संस्करण के बाद, लेकिन कुछ समय के लिए कार्यान्वयन द्वारा समर्थित किया गया है। ड्राफ्ट N4527 [14.5.7p3] में प्रासंगिक शब्द है:
हालांकि, यदि टेम्पलेट-आईडी निर्भर है, तो बाद में टेम्पलेट तर्क प्रतिस्थापन टेम्पलेट-आईडी पर लागू होता है। [उदाहरण:
template<typename...> using void_t = void;
template<typename T> void_t<typename T::foo> f();
f<int>(); // error, int does not have a nested type foo
अंत उदाहरण]
यहां एक संपूर्ण उदाहरण इस विचार को लागू करने के लिए:
#include <iostream>
#include <type_traits>
#include <utility>
template<typename> struct User { static void f() { std::cout << "primary\n"; } };
template<typename> struct Data { };
template<typename T, typename U> struct Derived1 : Data<T*> { };
template<typename> struct Derived2 : Data<double> { };
struct DD : Data<int> { };
template<typename T> void take_data(Data<T>&&);
template<typename T, typename = decltype(take_data(std::declval<T>()))>
using enable_if_data = T;
template<template<typename...> class TT, typename... Ts>
struct User<enable_if_data<TT<Ts...>>>
{
static void f() { std::cout << "partial specialization for Data\n"; }
};
template<typename> struct Other { };
template<typename T> struct User<Other<T>>
{
static void f() { std::cout << "partial specialization for Other\n"; }
};
int main()
{
User<int>::f();
User<Data<int>>::f();
User<Derived1<int, long>>::f();
User<Derived2<char>>::f();
User<DD>::f();
User<Other<int>>::f();
}
चल रहा है यह प्रिंट:
primary
partial specialization for Data
partial specialization for Data
partial specialization for Data
primary
partial specialization for Other
आप देख सकते हैं , एक झुर्रियां है: आंशिक विशेषज्ञता का चयन नहीं किया जाता है DD
, और यह नहीं हो सकता है, जिस तरह से हमने इसे घोषित किया है। तो, क्यों करते हैं हम सिर्फ
template<typename T> struct User<enable_if_data<T>>
कहना और यह DD
मिलान करने के लिए और साथ ही अनुमति नहीं? यह वास्तव में जीसीसी में काम करता है, लेकिन सही ढंग से (, [p8.3] भविष्य में गायब हो सकता है के रूप में यह अनावश्यक है - CWG 2033) बजना और MSVC द्वारा अस्वीकार कर दिया गया है की वजह से [14.5.5p8.3, 8.4]:
- विशेषज्ञता की तर्क सूची प्राथमिक टेम्पलेट की निहित तर्क सूची के समान नहीं होगी।
- विशेषज्ञता प्राथमिक टेम्पलेट (14.5.5.2) से अधिक विशिष्ट होगी।
User<enable_if_data<T>>
User<T>
(कि डिफ़ॉल्ट तर्क है, जो अलग रूप में ऊपर पहली बोली से समझाया नियंत्रित किया जाता है, में सापेक्ष प्रतिस्थापन), इस प्रकार आंशिक विशेषज्ञता के किसी अमान्य फ़ॉर्म के बराबर है।दुर्भाग्य से, DD
जैसे मिलान करने वाली चीजों को सामान्य रूप से T
के आंशिक विशेषज्ञता तर्क की आवश्यकता होगी - इसमें कोई अन्य रूप नहीं है और अभी भी हर मामले से मेल खाता है। इसलिए, मुझे डर है कि हम निश्चित रूप से कह सकते हैं कि इस हिस्से को दिए गए बाधाओं के भीतर हल नहीं किया जा सकता है। जब तक Data<T>
से व्युत्पन्न वर्ग खुद को कर रहे हैं टेम्पलेट विशेषज्ञताओं, (वहाँ Core issue 1980, जो टेम्पलेट उपनाम के उपयोग के संबंध में कुछ संभावित भविष्य के नियमों पर संकेत है, लेकिन मुझे शक है वे हमारे मामले वैध बना देंगे।)
आगे उन्हें बाधित उपर्युक्त तकनीक का उपयोग करके काम करेगा, इसलिए उम्मीद है कि यह आपके लिए कुछ उपयोग होगा।
संकलक समर्थन (इस मैं क्या परीक्षण किया है, अन्य संस्करणों के रूप में अच्छी तरह से काम कर सकते हैं):
- बजना 3.3 - 3.6.0,
-Wall -Wextra -std=c++11 -pedantic
साथ - जैसा कि ऊपर वर्णित काम करता है।
- जीसीसी 4.7.3 - 4.9.2, वही विकल्प - ऊपर जैसा ही है। उत्सुकता से, जीसीसी 5.1.0 - 5.2.0 अब कोड के सही संस्करण का उपयोग करके आंशिक विशेषज्ञता का चयन नहीं करता है। यह एक प्रतिगमन की तरह दिखता है। मेरे पास उचित बग रिपोर्ट को एक साथ रखने का समय नहीं है; अगर आप चाहें तो ऐसा करने में संकोच न करें। समस्या टेम्पलेट टेम्पलेट पैरामीटर के साथ पैरामीटर पैक के उपयोग से संबंधित प्रतीत होती है। वैसे भी, जीसीसी
enable_if_data<T>
का उपयोग कर गलत संस्करण स्वीकार करता है, ताकि यह एक अस्थायी समाधान हो।
- एमएसवीसी: दृश्य सी ++ 2015,
/W4
के साथ, ऊपर वर्णित अनुसार कार्य करता है। पुराने संस्करण डिफ़ॉल्ट तर्क में decltype
पसंद नहीं है, लेकिन तकनीक ही अभी भी काम करता है - को व्यक्त करने का एक और तरीका बाधा उस पर 2013 अद्यतन 4.
SFINAE काम करता है के साथ डिफ़ॉल्ट तर्क की जगह ** कर सकते हैं ** टेम्पलेट विशेषज्ञता चुनने के लिए आवेदन किया जाए, http://en.cppreference.com/w/cpp/types/enable_if – Walter
देखें तो यह कर सकता है! मैंने कुछ सीखा –
मुझे नहीं लगता कि मैं समझता हूं कि 'static_assert' संस्करण क्यों काम नहीं करेगा। विस्तृत करने के लिए परवाह? – jrok