Мне нужны просто словарь или ассоциативный массив string
=> int
.
Существует карта типа C++ для этого случая.
Но мне нужна только одна карта forall экземпляры (-> статичный), и эта карта не может быть изменена (-> константа);
Я нашел этот путь с библиотекой повышения
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();
};
#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() {
}
Я часто использую этот шаблон и рекомендую вам также использовать его:
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;
}
Здесь вам не только больше не нужно иметь дело с логической переменной, но и у вас не будет скрытая глобальная переменная, которая проверяется, если инициализатор статической переменной внутри функции уже был вызван.
Если вы считаете 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';
}
Полезно знать как такие вещи работают, особенно когда они такие короткие, но в этом случае я бы использовал функцию:
struct A {
static map<int, int> const m;
};
namespace {
map<int,int> create_map() {
map<int, int> m;
m[1] = 2; // etc.
return m;
}
}
map<int, int> const A::m = create_map();
Вызов функции не может появляться в константном выражении.
попробуйте следующее: (просто пример)
#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
}
Другой подход к проблеме:
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
}
Это более эффективно, так как нет однотипного копирования из стека в кучу (включая конструктор, деструкторы на всех элементах). Важно это или нет, зависит от вашего случая использования. Для строк это не имеет значения! (но вы можете найти или не найти эту версию "более чистой")
Если карта должна содержать только записи, которые известны на момент компиляции, и ключи карты - целые числа, то вам вообще не нужно использовать карту.
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
}
}