मैंने एक प्रकार-सुरक्षित आईडी क्लास बनाई है, लेकिन अब मैं ऑपरेटर ++ का समर्थन करना चाहता हूं यदि अंतर्निहित प्रकार में भी है। this और this answears से मैं 2 विकल्प के साथ आए हैं, लेकिन वे दोनों असफल जब सहायता के साथ instantiated:SFINAE केवल क्लास सदस्य होने के लिए
template<typename T, typename TID = unsigned int>
struct AId {
typedef AId<T, TID> type;
typedef T handled_type;
typedef TID value_type;
private:
value_type id;
template<typename _T> struct IsIncrementable
{
template<typename _U> using rm_ref = typename std::remove_reference<_U>::type;
typedef char (&yes)[1];
typedef char (&no)[2];
template<class _U>
static yes test(_U *data, typename std::enable_if<
std::is_same<_U, rm_ref<decltype(++(*data))>>::value
>::type * = 0);
static no test(...);
static const bool value = sizeof(yes) == sizeof(test((rm_ref<_T> *)0));
};
public:
explicit AId(const value_type &id) : id(id) {}
...
//This fails with error: no match for 'operator++' (operand type is
//'AId<some_type, std::basic_string<char> >::value_type
//{aka std::basic_string<char>}')
//auto operator++() -> decltype(++id, std::ref(type())) { ++id; return *this; }
// ^
template<typename = decltype(++id)>
auto operator++() -> decltype(++id, std::ref(type())) { ++id; return *this; }
//error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename std::enable_if<IsIncrementable<value_type>::value, int>::type = 0>
type operator++(int /*postfix*/) { type old(id); ++id; return old; }
};
कैसे AId<>
हो सकता है operator++
केवल AId<>::value_type
अगर यह भी है? मैं सी ++ 11 तक सीमित हूं और कोई बढ़ावा नहीं देता हूं।
पहले एक दूसरा प्रश्न था जिससे मैंने अपने here पर एक प्रश्न बना दिया था।
हालांकि मैं वास्तव में अपने कोड में @Sam Varshavchik answear का उपयोग कर रहा हूं, लेकिन मुझे लगता है कि @Guillaume Racicot द्वारा प्रदान किया गया एक अधिक सामान्य होने के लिए, इसलिए मैंने इसे एक समाधान के रूप में चुना।
अब मैं @ बैरी के answear का उपयोग कर रहा हूं जो कि सरल और सही दोनों है।
अच्छा answear, लेकिन इसके लिए @Sam Varshavchik की तुलना में अधिक कोड की आवश्यकता है। क्या कोई कारण है कि यह प्राथमिक है? मुझे लगता है कि यह वास्तव में SFINAE का उपयोग करता है, लेकिन यह एक आवश्यकता नहीं है, मैंने सोचा कि यह एकमात्र समाधान था। इसके अलावा, void_t की आपकी परिभाषा के संबंध में, [this] (http://en.cppreference.com/w/cpp/types/void_t) के अनुसार यह वास्तव में 'टेम्पलेट struct make_void {typedef void होना चाहिए टाइप;}; ' ' टेम्पलेट void_t = typename make_void :: टाइप; ' –
Olivetree
का उपयोग करके मेरा संपादन देखें। मैंने पहले अनुच्छेद –
में एक कारण जोड़ा है 'voider' या' make_void' नाम का कोई प्रभाव नहीं है। यह किसी भी मानक का हिस्सा नहीं है और उदाहरण में 'make_void'' चुना गया था। अगर नाम बदलने के लिए स्वतंत्र हो जाओ। –