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.

5
  • 1
    Have you tried defining a struct that contains a char[5]? Commented Jul 16, 2012 at 17:30
  • Why not char * or better yet string? Commented Jul 16, 2012 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 ? Commented Jul 16, 2012 at 17:38
  • @user - See this question Why declare a struct that only contains an array Commented Jul 16, 2012 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. Commented Jun 6, 2018 at 13:57

6 Answers 6

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Sorry, I cannot use boost library
The two > should be separated by a space character. Otherwise, it is treated as operator>>.
@timrau Not anymore in C++11. Have a look at here.
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;
}

2 Comments

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.
How to retrieve the data ? I used printf("%s\n", myMap[0].data) , but it does not work.
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];
};

/

1 Comment

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.)
0

Instead of:

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

Fill the position like this:

strncpy(myMap[0], arr, 5);

Comments

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########################*/

1 Comment

Looks like you added answer to wrong question...
-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

2 Comments

You only need to do comparisons on the key_type, not the mapped_type
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.