সি ++ তে কীভাবে কোনও প্রাইভেট স্ট্যাটিক কনস্ট মানচিত্র শুরু করতে হয়?


108

আমি শুধু অভিধান বা এসসিয়েতিভ আরে প্রয়োজন string=> int

এই ক্ষেত্রে মানচিত্র সি ++ রয়েছে।

তবে আমার কেবলমাত্র একটি মানচিত্রের ফোরাল দৃষ্টান্ত প্রয়োজন (-> স্থিতিশীল) এবং এই মানচিত্রটি (-> কনস্ট) পরিবর্তন করা যায় না;

আমি বুস্ট লাইব্রেরি সহ এইভাবে খুঁজে পেয়েছি

 std::map<int, char> example = 
      boost::assign::map_list_of(1, 'a') (2, 'b') (3, 'c');

এই lib ছাড়া অন্য সমাধান আছে? আমি এর মতো কিছু চেষ্টা করেছি, তবে মানচিত্রের সূচনাতে সবসময় কিছু সমস্যা থাকে।

class myClass{
private:
    static map<int,int> create_map()
        {
          map<int,int> m;
          m[1] = 2;
          m[3] = 4;
          m[5] = 6;
          return m;
        }
    static map<int,int> myMap =  create_map();

};

1
আপনি কোন বিষয়গুলি উল্লেখ করেন? আপনি কি অন্য মানচিত্রের স্থির পরিবর্তনশীল / ধ্রুবক থেকে এই মানচিত্রটি ব্যবহার করার চেষ্টা করছেন?
প্যাটার টারিক

এটি কোনও সহযোগী অ্যারে স্ট্রিং => ইনট নয়, আপনি একটি চরে কোনও ম্যাপ তৈরি করছেন। v = k + 'a' - 1
জনসিওয়েব

উত্তর:


107
#include <map>
using namespace std;

struct A{
    static map<int,int> create_map()
        {
          map<int,int> m;
          m[1] = 2;
          m[3] = 4;
          m[5] = 6;
          return m;
        }
    static const map<int,int> myMap;

};

const map<int,int> A:: myMap =  A::create_map();

int main() {
}

3
সরলতার জন্য +1, অবশ্যই একটি Boost.Assign
পছন্দসই

5
+1, ধন্যবাদ দ্রষ্টব্য: আমাকে আমার প্রয়োগের ফাইলে সূচনা লাইন রাখতে হয়েছিল; এটিকে হেডার ফাইলে রেখে দেওয়া একাধিক সংজ্ঞার কারণে আমাকে ত্রুটি দেয় (যখনই শিরোনামটি কোথাও অন্তর্ভুক্ত করা হত তখনই সূচনা কোডটি চলত)।
System.Cats.Lol

1
G ++ v4.7.3 সহ, এইটি সংকলিত হয়, যতক্ষণ না আমি cout << A::myMap[1];প্রবেশ করি main()। এটি একটি ত্রুটি দেয়। আমি constকোয়ালিফায়ারগুলিকে অপসারণ করলে ত্রুটিটি ঘটে না , তাই আমি অনুমান করি যে মানচিত্রটি operator[]একটি const map, কমপক্ষে, সি ++ লাইব্রেরির জি ++ প্রয়োগের ক্ষেত্রে হ্যান্ডেল করতে পারে না ।
ক্রেগ ম্যাককুইন

2
ত্রুটিটি হ'ল:const_map.cpp:22:23: error: passing ‘const std::map<int, int>’ as ‘this’ argument of ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = int; _Tp = int; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = int; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = int]’ discards qualifiers [-fpermissive]
ক্রেগ ম্যাককুইন

4
প্রকৃতপক্ষে, মানচিত্রের অপারেটর [] কোনও কনস্টের মানচিত্রে অপারেট করতে পারে না কারণ সেই অপারেটরটি উপস্থিত না থাকলে রেফারেন্সড এন্ট্রি তৈরি করে (যেহেতু এটি ম্যাপ করা মানকে একটি রেফারেন্স দেয়)। সি ++ 11 এ (কীভাল্ট কী) পদ্ধতিটি প্রবর্তন করে যা আপনাকে একটি নির্দিষ্ট কী দিয়ে আইটেমটি অ্যাক্সেস করতে দেয়, এটি উপস্থিত না থাকলে একটি ব্যতিক্রম ছুঁড়ে দেয়। ( en.cppreferences.com/w/cpp/container/map/at ) এই পদ্ধতিটি কনস্ট্যান্ট দৃষ্টান্তগুলিতে কাজ করবে তবে অ- কনস্ট্যান্ট ইভেন্টে কোনও উপাদান sertোকাতে ব্যবহার করা যাবে না ([] অপারেটরের মতো)।
এমবারজিএল

108

সি ++ 11 স্ট্যান্ডার্ড ইউনিফর্ম ইনিশিয়ালাইজেশন চালু করেছে যা আপনার সংকলক সমর্থন করে যদি এটি এত সহজ করে তোলে:

//myClass.hpp
class myClass {
  private:
    static map<int,int> myMap;
};


//myClass.cpp
map<int,int> myClass::myMap = {
   {1, 2},
   {3, 4},
   {5, 6}
};

আনর্ডারড_ম্যাপে পেশাদার সি ++ থেকে এই বিভাগটি দেখুন ।


আমাদের কি সিপিপি ফাইলে সমান চিহ্নের দরকার আছে?
0:55 এ ফোড করুন

@ ফোড: সমান চিহ্নটি অতিমাত্রায় is
জিনসেড

ব্যবহার দেখানোর জন্য আপনাকে ধন্যবাদ। স্থিতিশীল ভেরিয়েবলগুলি কীভাবে সংশোধন করা যায় তা বোঝার জন্য এটি সত্যই সহায়ক ছিল।
ব্যবহারকারী 9102d82

12

আমি এটা করেছি! :)

সি ++ 11 ছাড়া সূক্ষ্ম কাজ করে

class MyClass {
    typedef std::map<std::string, int> MyMap;

    struct T {
        const char* Name;
        int Num;

        operator MyMap::value_type() const {
            return std::pair<std::string, int>(Name, Num);
        }
    };

    static const T MapPairs[];
    static const MyMap TheMap;
};

const MyClass::T MyClass::MapPairs[] = {
    { "Jan", 1 }, { "Feb", 2 }, { "Mar", 3 }
};

const MyClass::MyMap MyClass::TheMap(MapPairs, MapPairs + 3);

11

আপনি যদি boost::assign::map_list_ofদরকারী মনে করেন তবে এটি কোনও কারণে ব্যবহার করতে না পারেন, আপনি নিজের লিখতে পারেন :

template<class K, class V>
struct map_list_of_type {
  typedef std::map<K, V> Map;
  Map data;
  map_list_of_type(K k, V v) { data[k] = v; }
  map_list_of_type& operator()(K k, V v) { data[k] = v; return *this; }
  operator Map const&() const { return data; }
};
template<class K, class V>
map_list_of_type<K, V> my_map_list_of(K k, V v) {
  return map_list_of_type<K, V>(k, v);
}

int main() {
  std::map<int, char> example = 
    my_map_list_of(1, 'a') (2, 'b') (3, 'c');
  cout << example << '\n';
}

এই জাতীয় জিনিসগুলি কীভাবে কাজ করে তা বিশেষত এগুলি সংক্ষিপ্ত হলে কীভাবে তা জেনে রাখা দরকারী তবে এই ক্ষেত্রে আমি একটি ফাংশন ব্যবহার করব:

a.hpp

struct A {
  static map<int, int> const m;
};

a.cpp

namespace {
map<int,int> create_map() {
  map<int, int> m;
  m[1] = 2; // etc.
  return m;
}
}

map<int, int> const A::m = create_map();

6

সমস্যার একটি পৃথক পদ্ধতি:

struct A {
    static const map<int, string> * singleton_map() {
        static map<int, string>* m = NULL;
        if (!m) {
            m = new map<int, string>;
            m[42] = "42"
            // ... other initializations
        }
        return m;
    }

    // rest of the class
}

এটি আরও দক্ষ, কারণ স্ট্যাক থেকে হিপ পর্যন্ত কোনও ধরণের একক অনুলিপি নেই (নির্মাণকারী, সমস্ত উপাদানগুলির ডেস্ট্রাক্টর সহ)। এটি গুরুত্বপূর্ণ কিনা আপনার ব্যবহারের ক্ষেত্রে নির্ভর করে। স্ট্রিং দিয়ে কিছু যায় আসে না! (তবে আপনি এই সংস্করণটি "ক্লিনার" বা পেতে পারেন না)


3
আরভিও আমার এবং নীলের উত্তরের অনুলিপি মুছে ফেলে।

6

যদি মানচিত্রে কেবলমাত্র এন্ট্রি থাকতে হবে যা সংকলনের সময় পরিচিত এবং মানচিত্রের কীগুলি পূর্ণসংখ্যা হয়, তবে আপনাকে কোনও মানচিত্র ব্যবহার করার দরকার নেই।

char get_value(int key)
{
    switch (key)
    {
        case 1:
            return 'a';
        case 2:
            return 'b';
        case 3:
            return 'c';
        default:
            // Do whatever is appropriate when the key is not valid
    }
}

5
মানচিত্রের প্রয়োজন নেই বলে উল্লেখ করার জন্য +1, তবে আপনি
এগুলি

4
যে switch, ভয়াবহ, যদিও। কেন হবে না return key + 'a' - 1?
জনসয়েব

12
@Johnsyweb। আমি ধরে নিই যে মূল পোস্টার সরবরাহ করা ম্যাপিংটি কেবলমাত্র একটি উদাহরণ হিসাবে উপস্থাপিত হয়েছিল এবং তার যে প্রকৃত ম্যাপিং রয়েছে তার সূচক নয়। অতএব, আমি এটিও ধরব যে return key + 'a' - 1এটি তার প্রকৃত ম্যাপিংয়ের জন্য কাজ করবে না।
ম্যাথু টি। স্টেবলার

3

আপনি এটি চেষ্টা করতে পারেন:

MyClass.h

class MyClass {
private:
    static const std::map<key, value> m_myMap; 
    static const std::map<key, value> createMyStaticConstantMap();
public:
    static std::map<key, value> getMyConstantStaticMap( return m_myMap );
}; //MyClass

MyClass.cpp

#include "MyClass.h"

const std::map<key, value> MyClass::m_myMap = MyClass::createMyStaticConstantMap();

const std::map<key, value> MyClass::createMyStaticConstantMap() {
    std::map<key, value> mMap;
    mMap.insert( std::make_pair( key1, value1 ) );
    mMap.insert( std::make_pair( key2, value2 ) );
    // ....
    mMap.insert( std::make_pair( lastKey, lastValue ) ); 
    return mMap;
} // createMyStaticConstantMap

এই বাস্তবায়নের সাথে সাথে আপনার ক্লাসগুলির ধ্রুবক স্ট্যাটিক মানচিত্রটি একটি ব্যক্তিগত সদস্য এবং পাবলিক গেট পদ্ধতি ব্যবহার করে অন্যান্য শ্রেণিতে অ্যাক্সেসযোগ্য হতে পারে। অন্যথায় এটি যেহেতু স্থির এবং পরিবর্তন করতে পারে না তাই আপনি পাবলিক পাবার পদ্ধতিটি মুছে ফেলতে এবং মানচিত্রের পরিবর্তনশীলটিকে শ্রেণীর পাবলিক বিভাগে স্থানান্তর করতে পারেন। আমি অবশ্য ক্রিয়েটম্যাপ পদ্ধতিটি ব্যক্তিগত বা সুরক্ষিত রাখি যদি উত্তরাধিকার এবং পলিমারফিজম প্রয়োজন হয়। এখানে ব্যবহারের কয়েকটি নমুনা দেওয়া হল।

 std::map<key,value> m1 = MyClass::getMyMap();
 // then do work on m1 or
 unsigned index = some predetermined value
 MyClass::getMyMap().at( index ); // As long as index is valid this will 
 // retun map.second or map->second value so if in this case key is an
 // unsigned and value is a std::string then you could do
 std::cout << std::string( MyClass::getMyMap().at( some index that exists in map ) ); 
// and it will print out to the console the string locted in the map at this index. 
//You can do this before any class object is instantiated or declared. 

 //If you are using a pointer to your class such as:
 std::shared_ptr<MyClass> || std::unique_ptr<MyClass>
 // Then it would look like this:
 pMyClass->getMyMap().at( index ); // And Will do the same as above
 // Even if you have not yet called the std pointer's reset method on
 // this class object. 

 // This will only work on static methods only, and all data in static methods must be available first.

আমি আমার মূল পোস্টটি সম্পাদনা করেছি, আমি যে মূল কোডটির জন্য পোস্ট করেছিলাম তাতে কোনও ভুল ছিল না যা সঠিকভাবে সংকলিত, নির্মিত এবং চালানো হয়েছিল, এটি ছিল আমার প্রথম সংস্করণটি উত্তর হিসাবে মানচিত্রটিকে সর্বজনীন হিসাবে ঘোষণা করা হয়েছিল এবং মানচিত্রটি ছিল কনস্ট কিন্তু অচল ছিল না।


2

আপনি যদি এমন একটি সংকলক ব্যবহার করছেন যা এখনও সর্বজনীন সূচনা সমর্থন করে না বা বুস্ট ব্যবহারে আপনার কাছে সংরক্ষণ রয়েছে, তবে অন্য সম্ভাব্য বিকল্পটি নীচের মত হবে

std::map<int, int> m = [] () {
    std::pair<int,int> _m[] = {
        std::make_pair(1 , sizeof(2)),
        std::make_pair(3 , sizeof(4)),
        std::make_pair(5 , sizeof(6))};
    std::map<int, int> m;
    for (auto data: _m)
    {
        m[data.first] = data.second;
    }
    return m;
}();

0

একটি ফাংশন কল একটি ধ্রুবক প্রকাশে উপস্থিত হতে পারে।

এটি চেষ্টা করুন: (কেবল একটি উদাহরণ)

#include <map>
#include <iostream>

using std::map;
using std::cout;

class myClass{
 public:
 static map<int,int> create_map()
    {
      map<int,int> m;
      m[1] = 2;
      m[3] = 4;
      m[5] = 6;
      return m;
    }
 const static map<int,int> myMap;

};
const map<int,int>myClass::myMap =  create_map();

int main(){

   map<int,int> t=myClass::create_map();
   std::cout<<t[1]; //prints 2
}

6
একটি ফাংশন অবশ্যই কনস্ট অবজেক্টটি আরম্ভ করার জন্য ব্যবহার করা যেতে পারে।

ওপির কোডটি static map<int,int> myMap = create_map();ভুল।
প্রসূন সৌরভ

3
প্রশ্নের কোডটি ভুল, আমরা সকলেই এতে একমত, তবে আপনি এই উত্তরে যেমন বলেছেন তেমন 'ধ্রুবক প্রকাশের' সাথে কোনও সম্পর্ক নেই, বরং আপনি কেবলমাত্র একটি শ্রেণির স্থির স্থিতিশীল সদস্যদের সূচনা করতে পারবেন এই সত্যের সাথে the ঘোষণা যদি তারা পূর্ণসংখ্যা বা এনাম টাইপের হয়। অন্যান্য সমস্ত ধরণের জন্য, সূচনাটি অবশ্যই সদস্য সংজ্ঞায় করতে হবে, ঘোষণা হিসাবে নয়।
ডেভিড রদ্রিগেজ - ড্রিবিস

নীলের উত্তরটি জি ++ দিয়ে সংকলন করে। তবুও, আমি জিএনইউ সরঞ্জামচেনের পূর্ববর্তী সংস্করণগুলিতে এই পদ্ধতির সাথে কিছু সমস্যা ছিল মনে আছে। একটি সর্বজনীন সঠিক উত্তর আছে?
বেসিলিভস

1
@ প্রসূন: সংকলক কী বলে তা আমি জানি না, তবে প্রশ্ন কোডের ত্রুটিটি ক্লাস ঘোষণায় শ্রেণীর ধরণের ধ্রুবক সদস্যের বৈশিষ্ট্যকে আরম্ভ করছে, সূচনাটি একটি ধ্রুবক প্রকাশ বা না তা নির্বিশেষে। যদি আপনি কোনও শ্রেণি সংজ্ঞায়িত করেন: struct testdata { testdata(int){} }; struct test { static const testdata td = 5; }; testdata test::td;এটি সূচনাটি ধ্রুবক অভিব্যক্তি ( 5) দ্বারা সঞ্চালিত হলেও সংকলন করতে ব্যর্থ হবে । তা হল, 'ধ্রুবক প্রকাশ' প্রাথমিক কোডের যথাযথতার (বা এর অভাব) অপ্রাসঙ্গিক।
ডেভিড রদ্রিগেজ - ড্রিবিস

-2

আমি প্রায়শই এই প্যাটার্নটি ব্যবহার করি এবং এটি ব্যবহার করার জন্য আপনাকেও সুপারিশ করি:

class MyMap : public std::map<int, int>
{
public:
    MyMap()
    {
        //either
        insert(make_pair(1, 2));
        insert(make_pair(3, 4));
        insert(make_pair(5, 6));
        //or
        (*this)[1] = 2;
        (*this)[3] = 4;
        (*this)[5] = 6;
    }
} const static my_map;

অবশ্যই এটি খুব পঠনযোগ্য নয়, তবে অন্য লিবস ছাড়া এটি করা ভাল। এছাড়াও আপনার প্রয়াসের মতো কোনও মানচিত্র থেকে অন্য ম্যাপে অনুলিপি করার মতো অপ্রয়োজনীয় ক্রিয়াকলাপ হবে না।

এটি ফাংশনের অভ্যন্তরে আরও বেশি কার্যকর: পরিবর্তে:

void foo()
{
   static bool initComplete = false;
   static Map map;
   if (!initComplete)
   {
      initComplete = true;
      map= ...;
   }
}

নিম্নলিখিত ব্যবহার:

void bar()
{
    struct MyMap : Map
    {
      MyMap()
      {
         ...
      }
    } static mymap;
}

বুলিয়ান ভেরিয়েবলের সাথে ডিল করার জন্য কেবল এখানে আপনার প্রয়োজন নেই, আপনার কাছে কোনও লুকানো বৈশ্বিক পরিবর্তনশীল নেই যা ফাংশনের অভ্যন্তরে স্ট্যাটিক ভেরিয়েবলের ইনিশিয়ালার ইতিমধ্যে বলা হয়েছিল কিনা তা পরীক্ষা করা হয়।


6
উত্তরাধিকার হ'ল সর্বশেষ সমাধানের হাতিয়ার হওয়া উচিত, প্রথম নয়।

আরভিও সমর্থন করে এমন একটি সংকলক ফাংশন সংস্করণগুলির সাহায্যে অনর্থক অনুলিপি মুছে ফেলে। সি ++ 0 এক্স মুভ শব্দার্থকগুলি উপলভ্য হয়ে গেলে, তাদের বাকিগুলি মুছে দেয়। যাই হোক না কেন, আমি সন্দেহ করি এটি একটি বাধা হবার কাছাকাছি।

রজার, আমি আরভিও, এবং অ্যান্ড স্যাথেন্টিকস সম্পর্কে ভাল জানি aware কোড এবং সত্তার স্বল্প পরিমাণে এটি এখনই একটি সমাধান a প্লাসের সমস্ত সি ++ 0 এক্স বৈশিষ্ট্য ফাংশন উদাহরণের অভ্যন্তরে স্থির বস্তুতে সহায়তা করবে না কারণ আমাদের ফাংশনের অভ্যন্তরে ফাংশনগুলি সংজ্ঞায়িত করার অনুমতি নেই।
পাভেল চিকুলাভ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.