error with static key map

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
Line 4 of your makefile is missing "-std=c++11".

Edit: also, line 3 should list main.o, not main.cpp
Last edited on
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
You shouldn't need map.h as a prerequisite for your rule to build map.o
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.