7

I want to define something like

Map<int, char[5] > myMap;

The above declaration is accepted by c++ compiler and no error is thrown but when I do something like this

int main()
{
    char arr[5] ="sdf";
    map <int, char[5]> myMap;
    myMap.insert(pair<int, char[5]>(0,arr));
    return 0;
}

I get error as:

In file included from /usr/include/c++/4.6/bits/stl_algobase.h:65:0,
                 from /usr/include/c++/4.6/bits/char_traits.h:41,
                 from /usr/include/c++/4.6/ios:41,
                 from /usr/include/c++/4.6/ostream:40,
                 from /usr/include/c++/4.6/iostream:40,
                 from charMap.cpp:1:
/usr/include/c++/4.6/bits/stl_pair.h: In constructor ‘std::pair<_T1, _T2>::pair(const _T1&, const _T2&) [with _T1 = int, _T2 = char [5]]’:
charMap.cpp:9:42:   instantiated from here
/usr/include/c++/4.6/bits/stl_pair.h:104:31: error: array used as initializer
/usr/include/c++/4.6/bits/stl_pair.h: In constructor ‘std::pair<_T1, _T2>::pair(const std::pair<_U1, _U2>&) [with _U1 = int, _U2 = char [5], _T1 = const int, _T2 = char [5]]’:
charMap.cpp:9:43:   instantiated from here
/usr/include/c++/4.6/bits/stl_pair.h:109:39: error: array used as initializer

It is important for me to define a fixed size character array because it optimizes my network stream operation. Is there any way to achieve it? I do not want to use char * or std::string.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Master Oogway
  • 461
  • 2
  • 5
  • 10
  • 1
    Have you tried defining a `struct` that contains a `char[5]`? – OmnipotentEntity Jul 16 '12 at 17:30
  • Why not `char *` or better yet `string`? –  Jul 16 '12 at 17:32
  • @OmnipotentEntity, yes I was able to do it by making it a struct :) But can you please explain me why did making it a struct work and not the char[5] itself ? – Master Oogway Jul 16 '12 at 17:38
  • @user - See this question [Why declare a struct that only contains an array](http://stackoverflow.com/questions/6966570/why-declare-a-struct-that-only-contains-an-array-in-c) – Bo Persson Jul 16 '12 at 17:53
  • 2
    Answers are great, but no one discussed why such a construct is not possible in c++, or if c++ compiler accepts the declaration, how to use it? Just from a theoretical point of view. – Sahil Singh Jun 06 '18 at 13:57

6 Answers6

9

I understand your performance requirements (since I do similar things too), but using character arrays in that way is rather unsafe.

If you have access to C++11 you could use std::array. Then you could define your map like:

map <int, array<char, 5>> myMap;

If you cannot use C++11, then you could use boost::array.

betabandido
  • 18,946
  • 11
  • 62
  • 76
3

One way is to wrap the fixed size character array as a struct.

struct FiveChar
{
   FiveChar(char in[5]) { memcpy(data, in, 5); }
   char& operator[](unsigned int idx) { return data[idx]; }
   char data[5];
};

int main(void)
{
   char arr[5] = "sdf";
   map<int, FiveChar> myMap;
   myMap.insert(pair<int, FiveChar>(0, arr));
   return 0;
}
timrau
  • 22,578
  • 4
  • 51
  • 64
  • 2
    You are basically reimplementing a simpler version of std/boost array. This solution might be useful if the OP does not have access to C++11 nor boost, otherwise there is not need to reinvent the wheel. – betabandido Jul 16 '12 at 17:48
  • How to retrieve the data ? I used printf("%s\n", myMap[0].data) , but it does not work. – user3658306 Apr 28 '16 at 18:49
1

You cannot use an array in a standard container.

  1. Use an std::vector instead of an array

  2. Use a map of pointers to arrays of 5 elements.

  3. Use boost tuples instead of arrays of 5 elements.

  4. Instead of using an array make a new struct that takes 3 elements. Make the map<int, newstructtype>. Or wrap your array in a struct and that will work too.

\

struct ArrayMap
{
    int color[5];
};

/

  • I have used raw char arrays in std containers. I'm trying to recall how I did it, but I most certainly did it. Vector wastes 24 bytes and an extra layer of indirection and reduced cache locality, not significant for one large vector but very wasteful for many vectors of 5 char each. std::string wastes 32bytes each, which assuming char[5], means 6 times the data consumption for the network stream in the question. (This sort of thing is a factor in the web has become so bloated.) – Max Power Jul 07 '22 at 21:13
0

Instead of:

myMap.insert(pair<int, char[5]>(0,arr));

Fill the position like this:

strncpy(myMap[0], arr, 5);
Luiz
  • 389
  • 3
  • 3
0

Assuming that the objective is to simplify the code writing use a writing trick. Let the compiler do the re-assignments of variables to pointers and integers: for example for variables wide and high, such as in a TIFF file, try

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

#define loc_wdth 30  /* location information on TIFF */
#define loc_hght 42  /* location information on TIFF */
main() {
 uint32_t  size;
 unsigned char *buff = calloc( 200000, sizeof( char));
  
 uint32_t *wide_o = (uint32_t *) &buff[ loc_wdth];
 uint32_t *high_o = (uint32_t *) &buff[ loc_hght];

#define wide    wide_o[ 0]
#define     high    high_o[ 0]

  buff[ loc_wdth] = 2;  /* reverse byte/bit order */
  buff[ loc_hght] = 3;
  
  printf("%x %x\n", buff[ loc_wdth], buff[ loc_hght]);

  size = wide * high;
  printf("w x h = %d x %d, size= %d\n", wide, high, size);

  wide = 16000; /* > 255, 2 bytes */
  high = 10000; /* > 255, 2 bytes */
  size = wide * high;   /* produces 4 byte result w/o 
using uint32_t any more */
  printf("w x h = %d x %d, size= %d\n", wide, high, size);
}
/*################## demo.c########################*/
Wolfram
  • 1
  • 1
-2

According to documentation pair can hold (and be defined for) distinct classes. C array is not a class, but a construct. You must define your own class with overloaded operator[](). Might need comparison operators as well

friendzis
  • 799
  • 6
  • 17
  • 2
    You only need to do comparisons on the `key_type`, not the `mapped_type` – Jonathan Wakely Jul 16 '12 at 17:36
  • Yes, in my case I needed the char array for the mapped type, therefore simply by making it a struct, it works for me. tyepdef struct { char arr[5]; } fixedArray; The above struct works for me. – Master Oogway Jul 16 '12 at 17:56