मैं टेम्पलेट का उपयोग कर प्रकार सुरक्षित सी ++ झंडे बनाने की कोशिश कर रहा हूं। मैं ध्वज और ध्वज एस (शून्य, एक या कई झंडे होने) के बीच अंतर करना चाहता हूं। नीचेप्रकार के लिए टेम्पलेट सुरक्षित सी ++ 11 एनम वर्ग झंडे
समाधान अच्छा काम करता है, EnumFlag<T> operator | (T, T)
किस प्रकार EnumFlag
वापस जाने के लिए enums पर सभी |
-operations का कारण बनता है के लिए छोड़कर। यह बहुत सारे कोड तोड़ता है। इसे ठीक करने के लिए कोई चाल? मेरे कोड में मैं निम्नलिखित करता हूं, हालांकि हार्ड कोडिंग Option
यहां कोई विकल्प नहीं है। यह सामान्य कैसे बनाएं?
EnumFlag<typename std::enable_if<std::is_same<T, Option>::value, T>::type> operator | (T l, T r)
को यह बदल रहा है ...
EnumFlag<T> operator | (T l, T r)
... कारण की सब कुछ टूट जाता है। मुझे ऐसा कुछ चाहिए (compilabel कोड नहीं)। या कोई अन्य बेहतर विचार!
EnumFlag<typename std::enable_if<std::already_expanded<EnumFlag<T>>::value, T>::type> operator | (T l, T r)
पूरा compilable कोड:
EnumFlag.h
#ifndef __classwith_flags_h_
#define __classwith_flags_h_
#include <type_traits>
enum class Option
{
PrintHi = 1 << 0,
PrintYo = 1 << 1,
PrintAlot = 1 << 2
};
template <typename T>
class EnumFlag
{
public:
using UnderlayingType = typename std::underlying_type<T>::type;
EnumFlag(const T& flags)
: m_flags(static_cast<UnderlayingType>(flags))
{}
bool operator & (T r) const
{
return 0 != (m_flags & static_cast<UnderlayingType>(r));
}
static const T NoFlag = static_cast<T>(0);
private:
UnderlayingType m_flags;
};
template<typename T>
EnumFlag<typename std::enable_if<std::is_same<T, Option>::value, T>::type> operator | (T l, T r)
{
return static_cast<T>(static_cast<typename EnumFlag<T>::UnderlayingType>(l) | static_cast<typename EnumFlag<T>::UnderlayingType>(r));
}
class ClassWithFlags
{
public:
using Options = EnumFlag <Option>;
void doIt(const Options &options);
};
#endif
EnumFlag.cpp
#include "EnumFlag.h"
#include <iostream>
void ClassWithFlags::doIt(const Options &options)
{
if (options & Option::PrintHi)
{
std::cout << "Hi" << std::endl;
}
if (options & Option::PrintYo)
{
std::cout << "Yo!" << std::endl;
}
}
int main()
{
ClassWithFlags classWithFlags;
classWithFlags.doIt(Option::PrintHi | Option::PrintAlot);
}
>DEMO <
वास्तविक कोड में बहुत अधिक ऑपरेटरों होंगे, हालांकि यह समस्या को स्पष्ट करने के लिए पर्याप्त है।
एक कम दखल समाधान इस (लेकिन अभी भी बहुत दखल)
template<typename T>
typename std::underlying_type<T>::type operator | (T l, T r)
{
return (static_cast<typename std::underlying_type<T>::type>(l) | static_cast<typename std::underlying_type<T>::type>(r));
}
नहीं भगवान के लिए पर्याप्त है, तो EnumFlag(const std::underlying_type<T> &flags)
मौजूद होना चाहिए और मैं प्रकार सुरक्षा खो देते हैं। साथ ही, मैं वैश्विक ऑपरेटर ओवरलोड को केवल वास्तव में आवश्यक प्रकारों के लिए बनाया जाना चाहता हूं। मैक्रोज़ भी कोई भगवान नहीं है क्योंकि मैं चाहता हूं कि 0 कक्षाओं के अंदर EnumFlag
की घोषणा की अनुमति दें। वैश्विक अधिभार वहां नहीं हो सकते हैं, इसलिए मुझे EnumFlag
पर बनाने के लिए अलग-अलग स्थानों पर दो मैक्रोज़ कॉल की आवश्यकता है।
समाधान शुद्ध सी ++ 11/एसएलएल होना चाहिए।
'EnumFlag से एक गैर स्पष्ट रूपांतरण जोड़ने नहीं चाहेंगे' टी करने के लिए ' 'EnumFlag ऑपरेटर के कारण होने वाले मुद्दों को ठीक करें। (टी एल, टी आर) '? –
Pradhan
मुझे लगता है कि यह एक कामकाज है, जिसे 'एनमफ्लैग' उदाहरण बनाते हैं जब आपको आवश्यकता नहीं होती है, बस वापस परिवर्तित करने के लिए। इसके अलावा 'विकल्प' के उदाहरण के साथ 'foo (const विकल्प & o)' को कॉल करने की अनुमति होगी। इसलिए, प्रकार खोना सुरक्षित। 'Foo' के अंदर हम सभी मामलों को एक हैंडलिंग कर सकते हैं, फिर भी कुछ नहीं होगा ... – Mathias
अपने झंडे को पकड़ने के लिए 'std :: bitset' के बारे में क्या? –