আমি কীভাবে এন + ক্লাসের মান সি ++ 11 এ আউটপুট দিতে পারি?


101

enum classC ++ 11 এ আমি কীভাবে আউটপুট করতে পারি ? সি ++ 03 এ এটির মতো:

#include <iostream>

using namespace std;

enum A {
  a = 1,
  b = 69,
  c= 666
};

int main () {
  A a = A::c;
  cout << a << endl;
}

সি ++ 0x এ এই কোডটি সংকলন করে না

#include <iostream>

using namespace std;

enum class A {
  a = 1,
  b = 69,
  c= 666
};

int main () {
  A a = A::c;
  cout << a << endl;
}


prog.cpp:13:11: error: cannot bind 'std::ostream' lvalue to 'std::basic_ostream<char>&&'
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/ostream:579:5: error:   initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char, _Traits = std::char_traits<char>, _Tp = A]'

Ideone.com এ সংকলিত


4
আপনি কেন এনাম আউটপুট দেওয়ার চেষ্টা করছেন?
এনম শ্রেণিটি এনএম

উত্তর:


126

একটি unscoped শুমার মতো একটি বিশ্লেষণ করা শুমার নয় পরোক্ষভাবে তার পূর্ণসংখ্যা মান পরিবর্তনীয়। একটি কাস্ট ব্যবহার করে আপনার স্পষ্টভাবে এটি পূর্ণসংখ্যায় রূপান্তর করতে হবে:

std::cout << static_cast<std::underlying_type<A>::type>(a) << std::endl;

আপনি যুক্তিটি কোনও ফাংশন টেম্পলেটে আবদ্ধ করতে চাইতে পারেন:

template <typename Enumeration>
auto as_integer(Enumeration const value)
    -> typename std::underlying_type<Enumeration>::type
{
    return static_cast<typename std::underlying_type<Enumeration>::type>(value);
}

হিসাবে ব্যবহার:

std::cout << as_integer(a) << std::endl;

4
এর পিছনে রিটার্ন টাইপ সিনট্যাক্স ব্যবহার করার কোনও কারণ আছে কি?
নিকল বোলাস

4
@ নিকলবোলাস: আমি as_integerআমার ওপেন-সোর্স লাইব্রেরি, সিএক্সএক্সআরফলেক্ট ( গণনা । Hpp দেখুন ) থেকে অনুলিপি করেছি । লাইব্রেরি সর্বত্র, সর্বদা ধারাবাহিকভাবে ফেরতের প্রকার ব্যবহার করে। ধারাবাহিকতার জন্য।
জেমস ম্যাকনেলিস

11
যদিও এটি 2 বছর দেরিতে হলেও, যদি অন্য কেউ এই প্রশ্নটি দেখে তবে আপনি কেবল উপরের কাস্ট কৌশল কৌশলটি ব্যবহার করতে পারেন এবং কেবল পূর্ণসংখ্যা পেতে "স্ট্যাটিক_কাস্ট <int> (মান)" বা "স্ট্যাটিক_কাস্ট <A> (ইনটাল্যু)" এ কল করতে পারেন একটি এনাম মান পেতে। শুধু মনে রাখবেন যে এনটিউ থেকে এনাম বা এনামে এনামে যাওয়া সমস্যার কারণ হতে পারে এবং সাধারণত একটি নকশা বাগের চিহ্ন।
বেনিয়ামিন ডেঞ্জার জনসন

4
কৌনিক কোণ বন্ধনী ছাড়া int (মান) এবং A (intValue) এছাড়াও কাজ করে।
গ্রেট

4
as_integerconstexprএমনটি সংজ্ঞায়িত করা যেতে পারে যাতে এটি এমন প্রসঙ্গে ব্যবহার করা যায় যেখানে ধ্রুবক অভিব্যক্তি প্রয়োজন।
নওয়াজ

40
#include <iostream>
#include <type_traits>

using namespace std;

enum class A {
  a = 1,
  b = 69,
  c= 666
};

std::ostream& operator << (std::ostream& os, const A& obj)
{
   os << static_cast<std::underlying_type<A>::type>(obj);
   return os;
}

int main () {
  A a = A::c;
  cout << a << endl;
}

আমি ভারব্যাটিমের এই উদাহরণটি অনুলিপি করেছি এবং এটি সংকলন করেছি g++ -std=c++0x enum.cppতবে আমি সংকলক ত্রুটির একটি গুচ্ছ পাচ্ছি -> পেস্টবিন . com/ জেএটিএলএক্সান 9 । আমি @ জেমস-এমকনেলিস থেকে সংকলন করতে উদাহরণটিও পাই না।
ডেনিস

4
@ ডেনিস অন্তর্নিহিত_প্রকারটি কেবল সি ++ 11 এ রয়েছে
ডেকিং

23

আপনার দ্বিতীয় উদাহরণটি পাওয়া (যেমন, স্কোপড এনাম ব্যবহার করা একটি) অনস্কেপড এনামগুলির মতো একই বাক্য গঠন ব্যবহার করে কাজ করা সম্ভব। তদুপরি, সমাধানটি জেনেরিক এবং সমস্ত স্কোপড এনামগুলির জন্য কাজ করবে, প্রতিটি স্কোপড এনামের জন্য বনাম লিখন কোড ( @ ফোরএভেআর দ্বারা প্রদত্ত উত্তরে দেখানো হয়েছে )।

সমাধানটি হ'ল একটি জেনেরিক operator<<ফাংশন লিখুন যা কোনও স্কোপড এনামের জন্য কাজ করবে। সমাধানটি SFINAE এর মাধ্যমে নিযুক্ত করে std::enable_ifএবং নিম্নরূপ।

#include <iostream>
#include <type_traits>

// Scoped enum
enum class Color
{
    Red,
    Green,
    Blue
};

// Unscoped enum
enum Orientation
{
    Horizontal,
    Vertical
};

// Another scoped enum
enum class ExecStatus
{
    Idle,
    Started,
    Running
};

template<typename T>
std::ostream& operator<<(typename std::enable_if<std::is_enum<T>::value, std::ostream>::type& stream, const T& e)
{
    return stream << static_cast<typename std::underlying_type<T>::type>(e);
}

int main()
{
    std::cout << Color::Blue << "\n";
    std::cout << Vertical << "\n";
    std::cout << ExecStatus::Running << "\n";
    return 0;
}

তোমার typenameআগে দরকার std::underlying_type<T>::type
uckelman

@ ইউকেলম্যান আপনি একেবারে সঠিক। আমার উত্তর আপডেট করার জন্য ধন্যবাদ।
জেমস অ্যাডকিসন

এটি আমার পক্ষে ঝাঁকুনির আওতায় কাজ করেছে তবে জিসিসি ৪.৯.২ এর অধীনে << এক সাথে শৃঙ্খলাবদ্ধ হয়ে ত্রুটি সহ এই সমাধানটি ব্যর্থ হয় error: cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’। এটি প্রদর্শিত হবে কারণ যখন স্ট্রিমটি অস্থায়ী হয় তখন ADL ব্যর্থ হয় এবং উপরের টেম্পলেটটি কোনও সম্ভাবনা নয়। কোন টিপস?
ofloveandhate

@ফ্লোভানডেট আপনি কি এমন উদাহরণের লিঙ্ক সরবরাহ করতে পারেন যা সমস্যাটি তৈরি করে? আমি উপরের কোডটি জিসিসি ৪.৯.২ এ পরীক্ষা করেছি কোন সমস্যা ছাড়াই এবং কেবলমাত্র একটি সামান্য পরিবর্তন, আমি অপারেটরগুলিকে এক সাথে জড়িত করে 3 টি coutস্টেটমেন্টকে একক coutবিবৃতিতে রূপান্তরিত করেছি <<এখানে
জেমস অ্যাডকিসন

আমাকে আমার বক্তব্য সংশোধন করতে দিন। আমি ক্লাসের বাইরে থাকা একটি ক্লাসের ভিতরে থাকা এনাম ক্লাসটি প্রিন্ট করার চেষ্টা করছিলাম। উপরের কোডটি অবশ্যই তাদের ক্লাসের মধ্যে নেই এমন এনাম ক্লাসের জন্য কাজ করে।
ofloveandhate

10

(আমাকে এখনও কোনও মন্তব্য করার অনুমতি নেই James) আমি জেমস ম্যাকনেলিসের ইতিমধ্যে দুর্দান্ত উত্তরের জন্য নিম্নলিখিত উন্নতিগুলি সুপারিশ করব:

template <typename Enumeration>
constexpr auto as_integer(Enumeration const value)
    -> typename std::underlying_type<Enumeration>::type
{
    static_assert(std::is_enum<Enumeration>::value, "parameter is not of type enum or enum class");
    return static_cast<typename std::underlying_type<Enumeration>::type>(value);
}

সঙ্গে

  • constexpr: কম্পাইল-টাইম অ্যারে আকার হিসাবে আমাকে এনাম সদস্যের মানটি ব্যবহার করার অনুমতি দিচ্ছে
  • static_assert+ is_enum: ফাংশনটি sth করে এমন সংকলন-সময়কে 'নিশ্চিত' করতে। প্রস্তাবিত হিসাবে কেবল গণনা সহ

যেভাবে আমি নিজেকে জিজ্ঞাসা করছি: আমি enum classযখন আমার এনাম সদস্যদের সংখ্যার মান নির্ধারণ করতে চাই তখন কেন আমি কখনই ব্যবহার করব ?! রূপান্তর প্রচেষ্টা বিবেচনা।

আমি enumএখানে পরামর্শ হিসাবে সম্ভবত আমি আবার সাধারণ ফিরে যেতে হবে : C ++ এ পতাকা হিসাবে enums কীভাবে ব্যবহার করবেন?


@ টবিস্পাইটের পরামর্শের ভিত্তিতে স্ট্যাটিক_সেসার্ট ছাড়া এটির আরও একটি (আরও ভাল) গন্ধ:

template <typename Enumeration>
constexpr std::enable_if_t<std::is_enum<Enumeration>::value,
std::underlying_type_t<Enumeration>> as_number(const Enumeration value)
{
    return static_cast<std::underlying_type_t<Enumeration>>(value);
}

এখানে কি এমন কোন ধরণের উপস্থিত রয়েছে Tযা মিথ্যা? যদি না হয় তবে এর সাথে কোনও মূল্য যুক্ত হয় না। std::underlying_type<T>::typestd::is_enum<T>::valuestatic_assert
টবির স্পিড

4
আমি সমস্ত সংকলক পরীক্ষা করিনি। তবে, @ টবিস্পাইট আপনি সম্ভবত সঠিক, এমএসভিসি ২০১৩ অনুধাবনযোগ্য ত্রুটি বার্তাগুলি ছড়িয়ে দিয়েছে বলে মনে হচ্ছে, অন্তর্নিহিত_প্রকার_আর বিদ্যমান এবং টাইপটি নিজেই এনামের মধ্যে 1 থেকে 1 যোগাযোগের পরামর্শ দেয়। এবং স্ট্যাটিক_সেটর এমনকি বরখাস্ত করা হয় না। তবে: রেফারেন্সটিতে বলা হয়েছে যে সম্পূর্ণ এনাম টাইপ সরবরাহ না করা হলে অন্তর্নিহিত_প্রকারের আচরণটি অপরিজ্ঞাত। সুতরাং স্থির_সেসਟਰ সর্বাধিক বোধগম্য বার্তা পাওয়ার ক্ষেত্রে কেবল একটি আশা। সম্ভবত এটির আগে / আর্লি প্রক্রিয়া করার জন্য জোর করার সম্ভাবনা রয়েছে?
ইয়াউ

হ্যাঁ হ্যাঁ, আপনি ঠিক বলেছেন যে এটি Enumerationসম্পূর্ণরূপে এনাম টাইপ না হলে এটি অপরিবর্তিত। যে ক্ষেত্রে এটি রিটার্ন টাইপ হিসাবে ব্যবহৃত হয়েছে, এটি ইতিমধ্যে খুব দেরিতে হতে পারে। সম্ভবত আমরা std::enable_if<std::is_enum<Enumeration>::value, std::underlying_type<Enumeration>::type>রিটার্ন টাইপ হিসাবে নির্দিষ্ট করতে পারে ? অবশ্যই, ধারণাগুলির জন্য সমর্থন সহ যদি আপনার একটি সংকলক থাকে তবে এটি এত সহজ (এবং ত্রুটির বার্তাগুলি এত বেশি পরিষ্কার হয়) ...
টবি স্পিড


3

নিম্নলিখিতটি আমার জন্য সি ++ 11 এ কাজ করেছেন:

template <typename Enum>
constexpr typename std::enable_if<std::is_enum<Enum>::value,
                                  typename std::underlying_type<Enum>::type>::type
to_integral(Enum const& value) {
    return static_cast<typename std::underlying_type<Enum>::type>(value);
}

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.