error with static key map

Jan 8, 2014 at 6:04pm
This error is driving me crazy.
I have reproduced the error in the simplified example below.

The last code tag contains the same example in one file, and it works.
So there is something about the way the code is broken up into more files and linked that is causing the error.

Thank you for taking a look.

Makefile:
1
2
3
4
5
6
7
8
9
10
11
12
13
all: a.exe

a.exe: main.cpp map.o
	g++ $^ -o $@

main.o: main.cpp
	g++ -Wall -std=c++11 -c main.cpp

map.o: map.cpp map.h
	g++ -Wall -std=c++11 -c map.cpp

clean:
	rm *.o


main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
#include "map.h"

// initialize static map out of class
// map must be compiled with: g++ -std=c++11 fileName.cpp
A::KeyMap A::km = {{1, 'a'}, {2, 'b'}};

int main()
{
	A a(1);

	std::cout << a.getChar(); // should print 'a'
}


map.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <map>

class A
{
	private:
		const int key;
		typedef std::map<const int, const char> KeyMap;
		static KeyMap km;
	public:
		A(const int k): key(k) { };
		char getChar() const { return km[key]; };
};


map.cpp:
 
#include "map.h" 


error message:

D:\wolf\Documents\teensy\demo_MinGW\map_link>make
g++ main.cpp map.o -o a.exe
main.cpp:4:38: error: in C++98 'A::km' must be initialized by constructor, not b
y '{...}'
 A::KeyMap A::km = {{1, 'a'}, {2, 'b'}}; // compiles w/o const
                                      ^
main.cpp:4:38: warning: extended initializer lists only available with -std=c++1
1 or -std=gnu++11 [enabled by default]
main.cpp:4:38: error: could not convert '{{1, 'a'}, {2, 'b'}}' from '<brace-encl
osed initializer list>' to 'A::KeyMap {aka std::map<const int, const char>}'
make: *** [a.exe] Error 1


When the same code is in one file it works fine:
map.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <map>

class A
{
	private:
		const int key;
		typedef std::map<const int, const char> KeyMap;
		static KeyMap km;
	public:
		A(const int k): key(k) { };
		char getChar() const { return km[key]; };
};
// initialize static map out of class
A::KeyMap A::km = {{1, 'a'}, {2, 'b'}};

int main()
{
	A a(1);

	std::cout << a.getChar(); // prints 'a'
}


Output when code is in one file:

D:\wolf\Documents\teensy\demo_MinGW>g++ -std=c++11 map.cpp

D:\wolf\Documents\teensy\demo_MinGW>a
a
Jan 8, 2014 at 6:15pm
Line 4 of your makefile is missing "-std=c++11".

Edit: also, line 3 should list main.o, not main.cpp
Last edited on Jan 8, 2014 at 6:16pm
Jan 8, 2014 at 6:40pm
line 3 should have read "main.o" instead of "main.cpp"

This works:
1
2
3
4
5
6
7
8
9
10
11
12
13
all: a.exe clean

a.exe: main.o map.o
	g++ $^ -o $@

main.o: main.cpp
	g++ -std=c++11 -Wall -c main.cpp

map.o: map.cpp map.h
	g++ -Wall -c map.cpp

clean:
	rm *.o
Jan 8, 2014 at 6:42pm
You shouldn't need map.h as a prerequisite for your rule to build map.o
Jan 8, 2014 at 7:33pm
Just to explain, The makefile originally had:
1
2
a.exe: main.cpp map.o
	g++ $^ -o $@


Which translated into:
g++ main.cpp map.o -o a.exe

main.o was never being created, thus it never got the -std=c++11 flag.

You might have noticed this if your "clean" was a more upfront:
1
2
clean:
	rm main.o map.o


When running clean, you would have got an error message about main.o not existing.

[quote]You shouldn't need map.h as a prerequisite for your rule to build map.o[/code]
You don't need it, but you want it. You also want it to be a prerequisite for main.o.
Topic archived. No new replies allowed.