error LNK2019 for constructor and destructor

The code returns a LNK2019 error for the constructor and destructor. This is older code that I cannot rewrite so I'd like to fix this error in VS2008.

the error is in the mail.obj file

LNK2019: unresolved external symbol "public: __thiscall FE_Iterator::~FE_Iterator(void)" referenced in function "public: __thiscall Set<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::Iterator::~Iterator(void)"

LNK2019: unresolved external symbol "public: __thiscall FE_Iterator::FE_Iterator(void)" referenced in function "private: __thiscall Set<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::Iterator::Iterator(class Set<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > *)"

This is the unresolved external symbol, there is not a cpp file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/*
 * File: foreach.h
 */

#ifndef _foreach_h
#define _foreach_h

#include "genlib.h"

/* These #includes are for files that contain "in" as a token */

#include <ios>
#include <fstream>
#include <sstream>

/* Redefine the ios constants (one of which is "in") */

static const ios::openmode IOS_APP = ios::app;
static const ios::openmode IOS_ATE = ios::ate;
static const ios::openmode IOS_BINARY = ios::binary;
static const ios::openmode IOS_IN = ios::in;
static const ios::openmode IOS_OUT = ios::out;
static const ios::openmode IOS_TRUNC = ios::trunc;

/*
 * Class: FE_Iterator
 */

class FE_Iterator {
public:
	FE_Iterator();
	~FE_Iterator();
};

/*
 * Class: FE_State
 */

class FE_State {
public:
	int state;
	FE_Iterator *iter;

	FE_State();
	~FE_State();
};

/*
 * Macro: foreach
 */

#define foreach(arg) \
  for (FE_State _fe; _fe.state < 2; ) \
    for (arg.foreachHook(_fe); _fe.state++ == 1; _fe.state = 0)

#define in =

#endif


this is the function referenced

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/*
 * File: set.h
 */

#ifndef _set_h
#define _set_h

#include "cmpfn.h"
#include "bst.h"
#include "vector.h"
#include "foreach.h"

/*
 * Class: Set
 */

template <typename ElemType>
class Set {

public:

/* Forward references */
	class Iterator;


	Set(int (*cmpFn)(ElemType, ElemType) = OperatorCmp);

	~Set();

	int size();

	bool isEmpty();

	void add(ElemType elem);

	void remove(ElemType elem);

	bool contains(ElemType elem);

/*
 * Method: find
 */
	ElemType *find(ElemType elem);

/*
 * Method: equals
 */
	bool equals(Set & otherSet);

/*
 * Method: isSubsetOf
 */
	bool isSubsetOf(Set & otherSet);

/*
 * Methods: unionWith, intersectWith, subtract
 */
	void unionWith(Set & otherSet);
	void intersectWith(Set & otherSet);
	void subtract(Set & otherSet);

/*
 * Method: clear
 */
	void clear();


/*
 * Method: mapAll
 */
	void mapAll(void (*fn)(ElemType elem));

/*
 * Method: mapAll
 */
	template <typename ClientDataType>
	void mapAll(void (*fn)(ElemType elem, ClientDataType & data),
	            ClientDataType & data);

/*
 * Method: iterator
 * Usage: iter = set.iterator();
 */
	Iterator iterator();

private:

#include "private/set.h"

};

#include "private/set.cpp"

#endif


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
 * File: private/set.h
 */


public:

/*
 * Legacy function: intersect
 */
	void intersect(Set & otherSet);

/*
 * Class: Set<ElemType>::Iterator
 */
	class Iterator : public FE_Iterator {
	public:
		Iterator();
		bool hasNext();
		ElemType next();

	private:
		Iterator(Set *setptr);
		typename BST<ElemType>::Iterator iterator;
		friend class Set;
	};
	friend class Iterator;
	ElemType foreachHook(FE_State & _fe);


private:
	BST<ElemType> bst;
	int (*cmpFn)(ElemType, ElemType);


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*
 * File: private/set.cpp
 */

#ifdef _set_h


template <typename ElemType>
Set<ElemType>::Set(int (*cmp)(ElemType, ElemType)) : bst(cmp) {
	cmpFn = cmp;
}

template <typename ElemType>
Set<ElemType>::~Set() {
	/* Empty */
}

template <typename ElemType>
int Set<ElemType>::size() {
	return bst.size();
}

template <typename ElemType>
bool Set<ElemType>::isEmpty() {
	return bst.isEmpty();
}

template <typename ElemType>
void Set<ElemType>::add(ElemType element) {
	bst.add(element);
}

template <typename ElemType>
void Set<ElemType>::remove(ElemType element) {
	bst.remove(element);
}

template <typename ElemType>
bool Set<ElemType>::contains(ElemType element) {
	return find(element) != NULL;
}

template <typename ElemType>
ElemType *Set<ElemType>::find(ElemType element) {
	return bst.find(element);
}

template <typename ElemType>
void Set<ElemType>::clear() {
	bst.clear();
}


template <typename ElemType>
bool Set<ElemType>::equals(Set & otherSet) {
	if (cmpFn != otherSet.cmpFn) {
		Error("Equals: sets have different comparison functions");
	}
	Iterator thisItr = iterator(), otherItr = otherSet.iterator();
	while (thisItr.hasNext() && otherItr.hasNext()) {
		if (cmpFn(thisItr.next(), otherItr.next()) != 0) return false;
	}
	return !thisItr.hasNext() && !otherItr.hasNext();
}

template <typename ElemType>
bool Set<ElemType>::isSubsetOf(Set & otherSet) {
	if (cmpFn != otherSet.cmpFn) {
		Error("isSubsetOf: sets have different comparison functions");
	}
	Iterator iter = iterator();
	while (iter.hasNext()) {
		if (!otherSet.contains(iter.next())) return false;
	}
	return true;
}

template <typename ElemType>
void Set<ElemType>::unionWith(Set & otherSet) {
	if (cmpFn != otherSet.cmpFn) {
		Error("unionWith: sets have different comparison functions");
	}
	Iterator iter = otherSet.iterator();
	while (iter.hasNext()) {
		add(iter.next());
	}
}

/*
 * Implementation notes: intersectWith
 */

template <typename ElemType>
void Set<ElemType>::intersectWith(Set & otherSet) {
	if (cmpFn != otherSet.cmpFn) {
		Error("intersectWith:"
		      " sets have different comparison functions");
	}
	Iterator iter = iterator();
	Vector<ElemType> toDelete;
	while (iter.hasNext()) {
		ElemType elem = iter.next();
		if (!otherSet.contains(elem)) toDelete.add(elem);
	}
	for (int i = 0; i < toDelete.size(); i++) {
		remove(toDelete[i]);
	}
}

template <typename ElemType>
void Set<ElemType>::intersect(Set & otherSet) {
	if (cmpFn != otherSet.cmpFn) {
		Error("intersect: sets have different comparison functions");
	}
	intersectWith(otherSet);
}

template <typename ElemType>
void Set<ElemType>::subtract(Set & otherSet) {
	if (cmpFn != otherSet.cmpFn) {
		Error("subtract: sets have different comparison functions");
	}
	Iterator iter = otherSet.iterator();
	while (iter.hasNext()) {
		remove(iter.next());
	}
}

template <typename ElemType>
void Set<ElemType>::mapAll(void (*fn)(ElemType)) {
	bst.mapAll(fn);
}

template <typename ElemType>
template <typename ClientDataType>
void Set<ElemType>::mapAll(void (*fn)(ElemType, ClientDataType &),
                           ClientDataType & data) {
	bst.mapAll(fn, data);
}

/*
 * Set::Iterator class implementation
 * The Iterator for Set relies on the underlying implementation of the
 * Iterator for the BST class.
 */

template <typename ElemType>
Set<ElemType>::Iterator::Iterator() {
	/* Empty */
}

template <typename ElemType>
typename Set<ElemType>::Iterator Set<ElemType>::iterator() {
	return Iterator(this);
}

template <typename ElemType>
Set<ElemType>::Iterator::Iterator(Set *setptr) {
	iterator = setptr->bst.iterator();
}

template <typename ElemType>
bool Set<ElemType>::Iterator::hasNext() {
	return iterator.hasNext();
}

template <typename ElemType>
ElemType Set<ElemType>::Iterator::next() {
	return iterator.next();
}

template <typename ElemType>
ElemType Set<ElemType>::foreachHook(FE_State & fe) {
	if (fe.state == 0) fe.iter = new Iterator(this);
	if (((Iterator *) fe.iter)->hasNext()) {
		fe.state = 1;
		return ((Iterator *) fe.iter)->next();
	} else {
		fe.state = 2;
		return ElemType();
	}
}

#endif
There's no source file...? That sounds like your problem, unless you're linking in a library or something. The linker is complaining that the header you're including has a constructor and destructor defined but it can't find the source for them.
i.e. you declared FE_Iterator and FE_State constructors and destructors but you don't have a definition of them.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class FE_Iterator {
public:
	FE_Iterator(){//write the definition here (if any)}
	~FE_Iterator(){//write the definition here (if any)}
};


class FE_State {
public:
//consider putting these 2 as private members
	int state;
	FE_Iterator *iter;

//provide a definition of these 2 within curly brackets {}
	FE_State();
	~FE_State();
};
I cannot find the foreach.cpp file after searching google code, a sourceForge library, and asking someone that should have it - I agree that there must be one. Can the definition be guessed based on the header file and standard constructors and destructors? I looked at lexicon and iterator files but don't know enough to modify their code for the foreach. But it should be a couple lines at most.
closed account (zb0S216C)
Template definitions cannot appear in a source file. See my answer here:
http://www.cplusplus.com/forum/beginner/73413/#msg392321

Wazzak
I see, so this header file is incomplete not that the source file is missing. I looked at versions of the foreach.h file from different sources and they are the same - I can recheck. If I understand you correctly, the foreach.h file is missing the definitions.
closed account (zb0S216C)
Template definitions must be in a header, but non-template classes can be in source files. Though, I don't see the corresponding definitions of FE_Iterator. These definitions, however, can appear in a source file.

Wazzak
can we write the missing definitions - where can I find sample code?
closed account (zb0S216C)
forestPeterson wrote:
"can we write the missing definitions"

Yes, of course you can.

forestPeterson wrote:
"where can I find sample code?"

No idea. I would make a sample myself, but I don't know how it's supposed to be implemented.

Wazzak
me to
Topic archived. No new replies allowed.