www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Link error even in single source file when having template

reply Sukit Tretriluxana <Sukit_member pathlink.com> writes:
My previous message described link errors when having templates in many source
file. I tried consolidating all of them into one and the problem is still there
with some differences. Try compiling the following program with 0.93 dmd.

Sukit

===========================
test.d
===========================
public interface Iterator(ValueType) {
public bool hasNext();
public ValueType next();
}

public interface Collection(ValueType) {

public bool add(ValueType val);
public bool addAll(.Collection!(ValueType) col);
public void clear();
public bool contains(ValueType val);
public bool containsAll(.Collection!(ValueType) col);
public bool isEmpty();
public Iterator!(ValueType) iterator();
public bool remove(ValueType val);
public bool removeAll(.Collection!(ValueType) col);
public bool retainAll(.Collection!(ValueType) col);
public int size();
public ValueType[] toArray();
public void toArray(ValueType[] array);

}

public interface List(ValueType) : Collection!(ValueType) {

public void addAt(int index, ValueType val);
public void addAllAt(int index, Collection!(ValueType) col);
public ValueType get(int index);
public int indexOf(ValueType val);
public int lasIndexOf(ValueType val);
public ValueType removeAt(int index);
public ValueType set(int index, ValueType val);
public .List!(ValueType) subList(int fromIndex, int toIndex);

}

public class ArrayList(ValueType) : List!(ValueType) {
private int curSize;
private ValueType[] values; 
private int incExpcurSize;

public this() {
this(100, 100);
}

public this(int initCapacity) {
this(initCapacity, 100);
}

public this(int initCapacity, int incExpcurSize) {
curSize = 0;
values.length = initCapacity;
incExpcurSize = incExpcurSize;
}

public bool add(ValueType val) {
ensurecurSize(curSize + 1);
values[curSize++] = val;
return true;
}

public void addAt(int index, ValueType val) {
ensurecurSize(curSize + 1);
shiftRight(index, 1);
values[index] = val;
}

public bool addAll(Collection!(ValueType) col) {
Iterator!(ValueType) itor = col.iterator();
while(itor.hasNext()) {
add(itor.next());
}
return true;
}

public void addAllAt(int index, Collection!(ValueType) col) {
ensurecurSize(curSize + col.size);
shiftRight(index, col.size);
Iterator!(ValueType) itor = col.iterator();
for(int i = index; itor.hasNext(); ++i) {
values[i] = itor.next();
}
}

public void clear() {
curSize = 0;
}

public bool contains(ValueType val) {
return indexOf(val) != -1;
}

public bool containsAll(Collection!(ValueType) col) {
Iterator!(ValueType) itor = col.iterator();
while(itor.hasNext()) {
if(!contains(itor.next())) {
return false;
}
}
return true;
}

public bool isEmpty() {
return curSize == 0;
}

public Iterator!(ValueType) iterator() {
return new ArrayListIterator!(ValueType)(curSize, values);
// return new ArrayListIterator!(ValueType)(curSize, curSize);
}

public ValueType get(int index) {
return values[index];
}

public int indexOf(ValueType val) {
for(int i = 0; i < curSize; ++i) {
if(values[i] == val) {
return i;
}
}
return -1;
}

public int lasIndexOf(ValueType val) {
for(int i = curSize - 1; i >= 0; --i) {
if(values[i] == val) {
return i;
}
}
return -1;
}

public ValueType set(int index, ValueType val) {
ValueType oldval = values[index];
values[index] = val;
return oldval;
}

public int size() {
return curSize;
}

public List!(ValueType) subList(int fromIndex, int toIndex) {
int count = toIndex - fromIndex;
ArrayList!(ValueType) subl = new .ArrayList!(ValueType)(count);
subl.values[] = this.values[fromIndex..toIndex];
return subl;
}

public bool remove(ValueType val) {
int pos = indexOf(val);
if(pos != -1) {
shiftLeft(pos, 1);
--curSize;
return true;
}
return false;
}

public ValueType removeAt(int index) {
ValueType oldval = values[index];
shiftLeft(index, 1);
--curSize;
return oldval;
}

public bool removeAll(Collection!(ValueType) col) {
bool changed = false;
Iterator!(ValueType) itor = col.iterator();
while(itor.hasNext()) {
changed = remove(itor.next()) || changed;
}
return changed;
}

public bool retainAll(Collection!(ValueType) col) {
bool changed = false;
for(int index = 0; index < curSize; ) {
if(col.contains(values[index])) {
++index;
} else {
removeAt(index);
changed = true;
}
}
return changed;
}

public ValueType[] toArray() {
ValueType[] result = new ValueType[curSize];
result[] = values;
return result;
}

public void toArray(ValueType[] array) {
array[] = values;

}

private void ensurecurSize(int reqcurSize) {
if(reqcurSize > values.length) {
int newcurSize = reqcurSize - curSize <= incExpcurSize
? incExpcurSize : reqcurSize + incExpcurSize;
values.length = newcurSize;
}
}

private void shiftLeft(int startIndex, int offset) {
for(int index = startIndex; index < curSize; --index) {
values[index - offset] = values[index];
}
}

private void shiftRight(int startIndex, int offset) {
for(int index = curSize - 1; index < startIndex; --index) {
values[index + offset] = values[index];
}
}
}

public class ArrayListIterator(ValueType) : Iterator!(ValueType) {
private int curSize, index;
private ValueType[] data;

public this(int curSize, ValueType[] data) {
// public this(int curSize, int data) {
this.curSize = curSize;
this.data = data;
// this.curSize = data;
index = 0;
}

public bool hasNext() {
return index < curSize;
}

public ValueType next() {
return data[index++];
}
}

void main()
{
ArrayList!(int) iarray = new ArrayList!(int)();
iarray.iterator();
}
Jun 25 2004
parent reply J C Calvarese <jcc7 cox.net> writes:
Sukit Tretriluxana wrote:
 My previous message described link errors when having templates in many source
 file. I tried consolidating all of them into one and the problem is still there
 with some differences. Try compiling the following program with 0.93 dmd.
 
 Sukit
 
 ===========================
 test.d
 ===========================

I don't know what the problem is, but I took out enough code to get it compile. (Of course, I'm sure I also removed the cool functionality that you were trying to get working.) I had a theory the you were trying to do illegal things with the interface (like "new"ing it), but the theory didn't pan out. You might be able to make some progress by removing functions until you get the smallest set of code with an error. Or if you want to work off the code I provide below, you could try adding back functionaity until it works. It's possible there's even a compiler bug involved, but it's impossible for me to tell without a much smaller test case. /+public interface Iterator(ValueType) { public bool hasNext(); public ValueType next(); }+/ public interface Collection(ValueType) { public bool add(ValueType val); public bool addAll(.Collection!(ValueType) col); public void clear(); public bool contains(ValueType val); public bool containsAll(.Collection!(ValueType) col); public bool isEmpty(); //public Iterator!(ValueType) iterator(); public bool remove(ValueType val); /// public bool removeAll(.Collection!(ValueType) col); public bool retainAll(.Collection!(ValueType) col); public int size(); public ValueType[] toArray(); public void toArray(ValueType[] array); } public interface List(ValueType) : Collection!(ValueType) { public void addAt(int index, ValueType val); public void addAllAt(int index, Collection!(ValueType) col); public ValueType get(int index); public int indexOf(ValueType val); public int lasIndexOf(ValueType val); public ValueType removeAt(int index); public ValueType set(int index, ValueType val); // public .List!(ValueType) subList(int fromIndex, int toIndex); } /+public+/ class ArrayList(ValueType) : List!(ValueType) { private int curSize; private ValueType[] values; private int incExpcurSize; public this() { this(100, 100); } public this(int initCapacity) { this(initCapacity, 100); } public this(int initCapacity, int incExpcurSize) { /+ curSize = 0; values.length = initCapacity; incExpcurSize = incExpcurSize;+/ } public bool add(ValueType val) { /+ ensurecurSize(curSize + 1); values[curSize++] = val;+/ return true; } public void addAt(int index, ValueType val) { /+ ensurecurSize(curSize + 1); shiftRight(index, 1);+/ values[index] = val; } public bool addAll(Collection!(ValueType) col) { /+ Iterator!(ValueType) itor = col.iterator(); while(itor.hasNext()) { add(itor.next()); }+/ return true; } public void addAllAt(int index, Collection!(ValueType) col) { /+ ensurecurSize(curSize + col.size); shiftRight(index, col.size); Iterator!(ValueType) itor = col.iterator(); for(int i = index; itor.hasNext(); ++i) { values[i] = itor.next(); }+/ } public void clear() { // curSize = 0; } public bool contains(ValueType val) { return indexOf(val) != -1; } public bool containsAll(Collection!(ValueType) col) { /+ Iterator!(ValueType) itor = col.iterator(); while(itor.hasNext()) { if(!contains(itor.next())) { return false; } }+/ return true; } public bool isEmpty() { return curSize == 0; } /+ ********* I don't think this will work. You can't "return" an interface. ********* public Iterator!(ValueType) iterator() { return new ArrayListIterator!(ValueType)(curSize, values); // return new ArrayListIterator!(ValueType)(curSize, curSize); } +/ public ValueType get(int index) { return values[index]; } public int indexOf(ValueType val) { /+ for(int i = 0; i < curSize; ++i) { if(values[i] == val) { return i; } }+/ return -1; } public int lasIndexOf(ValueType val) { /+ for(int i = curSize - 1; i >= 0; --i) { if(values[i] == val) { return i; } }+/ return -1; } public ValueType set(int index, ValueType val) { ValueType oldval = values[index]; values[index] = val; return oldval; } public int size() { return curSize; } /+ ****************** The problem? ******************* public List!(ValueType) subList(int fromIndex, int toIndex) { int count = toIndex - fromIndex; /+Array+/ List!(ValueType) subl = new ./+Array+/List!(ValueType)(count); subl.values[] = this.values[fromIndex..toIndex]; return subl; }+/ public bool remove(ValueType val) { /+ int pos = indexOf(val); if(pos != -1) { shiftLeft(pos, 1); --curSize; return true; }+/ return false; } public ValueType removeAt(int index) { ValueType oldval = values[index]; shiftLeft(index, 1); --curSize; return oldval; } /+ **** Same issue as earlier **** public bool removeAll(Collection!(ValueType) col) { bool changed = false; Iterator!(ValueType) itor = col.iterator(); while(itor.hasNext()) { changed = remove(itor.next()) || changed; } return changed; } +/ public bool retainAll(Collection!(ValueType) col) { bool changed = false; for(int index = 0; index < curSize; ) { if(col.contains(values[index])) { ++index; } else { removeAt(index); changed = true; } } return changed; } public ValueType[] toArray() { ValueType[] result = new ValueType[curSize]; result[] = values; return result; } public void toArray(ValueType[] array) { // array[] = values; } private void ensurecurSize(int reqcurSize) { /+ if(reqcurSize > values.length) { int newcurSize = reqcurSize - curSize <= incExpcurSize ? incExpcurSize : reqcurSize + incExpcurSize; values.length = newcurSize; }+/ } private void shiftLeft(int startIndex, int offset) { /+ for(int index = startIndex; index < curSize; --index) { values[index - offset] = values[index]; }+/ } private void shiftRight(int startIndex, int offset) { /+ for(int index = curSize - 1; index < startIndex; --index) { values[index + offset] = values[index]; }+/ } } public class ArrayListIterator(ValueType) : Iterator!(ValueType) { private int curSize, index; private ValueType[] data; public this(int curSize, ValueType[] data) { // public this(int curSize, int data) { this.curSize = curSize; this.data = data; // this.curSize = data; index = 0; } public bool hasNext() { return index < curSize; } public ValueType next() { return data[index++]; } } alias ArrayList!(int) ArrayListInt; void main() { ArrayList!(int) iarray = new ArrayList!(int)(); // iarray.iterator(); } -- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/
Jun 27 2004
parent reply Sukit Tretriluxana <Sukit_member pathlink.com> writes:
Hi Justin and everyone,

I appreciate your suggestion. I will try to remove the unneccessary code until
it becomes smallest but is still able to produce the errors.

You mentioned that I cannot return an interface. I am not sure I understand
that. From my understanding, an interface is just another type, which should be
allowed to be specified as a return type. Could you please elaborate a little
bit more on this?

Thanks,
Sukit

In article <cbnqlp$1tla$1 digitaldaemon.com>, J C Calvarese says...
Sukit Tretriluxana wrote:
 My previous message described link errors when having templates in many source
 file. I tried consolidating all of them into one and the problem is still there
 with some differences. Try compiling the following program with 0.93 dmd.
 
 Sukit
 
 ===========================
 test.d
 ===========================

I don't know what the problem is, but I took out enough code to get it compile. (Of course, I'm sure I also removed the cool functionality that you were trying to get working.) I had a theory the you were trying to do illegal things with the interface (like "new"ing it), but the theory didn't pan out. You might be able to make some progress by removing functions until you get the smallest set of code with an error. Or if you want to work off the code I provide below, you could try adding back functionaity until it works. It's possible there's even a compiler bug involved, but it's impossible for me to tell without a much smaller test case. /+public interface Iterator(ValueType) { public bool hasNext(); public ValueType next(); }+/ public interface Collection(ValueType) { public bool add(ValueType val); public bool addAll(.Collection!(ValueType) col); public void clear(); public bool contains(ValueType val); public bool containsAll(.Collection!(ValueType) col); public bool isEmpty(); //public Iterator!(ValueType) iterator(); public bool remove(ValueType val); /// public bool removeAll(.Collection!(ValueType) col); public bool retainAll(.Collection!(ValueType) col); public int size(); public ValueType[] toArray(); public void toArray(ValueType[] array); } public interface List(ValueType) : Collection!(ValueType) { public void addAt(int index, ValueType val); public void addAllAt(int index, Collection!(ValueType) col); public ValueType get(int index); public int indexOf(ValueType val); public int lasIndexOf(ValueType val); public ValueType removeAt(int index); public ValueType set(int index, ValueType val); // public .List!(ValueType) subList(int fromIndex, int toIndex); } /+public+/ class ArrayList(ValueType) : List!(ValueType) { private int curSize; private ValueType[] values; private int incExpcurSize; public this() { this(100, 100); } public this(int initCapacity) { this(initCapacity, 100); } public this(int initCapacity, int incExpcurSize) { /+ curSize = 0; values.length = initCapacity; incExpcurSize = incExpcurSize;+/ } public bool add(ValueType val) { /+ ensurecurSize(curSize + 1); values[curSize++] = val;+/ return true; } public void addAt(int index, ValueType val) { /+ ensurecurSize(curSize + 1); shiftRight(index, 1);+/ values[index] = val; } public bool addAll(Collection!(ValueType) col) { /+ Iterator!(ValueType) itor = col.iterator(); while(itor.hasNext()) { add(itor.next()); }+/ return true; } public void addAllAt(int index, Collection!(ValueType) col) { /+ ensurecurSize(curSize + col.size); shiftRight(index, col.size); Iterator!(ValueType) itor = col.iterator(); for(int i = index; itor.hasNext(); ++i) { values[i] = itor.next(); }+/ } public void clear() { // curSize = 0; } public bool contains(ValueType val) { return indexOf(val) != -1; } public bool containsAll(Collection!(ValueType) col) { /+ Iterator!(ValueType) itor = col.iterator(); while(itor.hasNext()) { if(!contains(itor.next())) { return false; } }+/ return true; } public bool isEmpty() { return curSize == 0; } /+ ********* I don't think this will work. You can't "return" an interface. ********* public Iterator!(ValueType) iterator() { return new ArrayListIterator!(ValueType)(curSize, values); // return new ArrayListIterator!(ValueType)(curSize, curSize); } +/ public ValueType get(int index) { return values[index]; } public int indexOf(ValueType val) { /+ for(int i = 0; i < curSize; ++i) { if(values[i] == val) { return i; } }+/ return -1; } public int lasIndexOf(ValueType val) { /+ for(int i = curSize - 1; i >= 0; --i) { if(values[i] == val) { return i; } }+/ return -1; } public ValueType set(int index, ValueType val) { ValueType oldval = values[index]; values[index] = val; return oldval; } public int size() { return curSize; } /+ ****************** The problem? ******************* public List!(ValueType) subList(int fromIndex, int toIndex) { int count = toIndex - fromIndex; /+Array+/ List!(ValueType) subl = new ./+Array+/List!(ValueType)(count); subl.values[] = this.values[fromIndex..toIndex]; return subl; }+/ public bool remove(ValueType val) { /+ int pos = indexOf(val); if(pos != -1) { shiftLeft(pos, 1); --curSize; return true; }+/ return false; } public ValueType removeAt(int index) { ValueType oldval = values[index]; shiftLeft(index, 1); --curSize; return oldval; } /+ **** Same issue as earlier **** public bool removeAll(Collection!(ValueType) col) { bool changed = false; Iterator!(ValueType) itor = col.iterator(); while(itor.hasNext()) { changed = remove(itor.next()) || changed; } return changed; } +/ public bool retainAll(Collection!(ValueType) col) { bool changed = false; for(int index = 0; index < curSize; ) { if(col.contains(values[index])) { ++index; } else { removeAt(index); changed = true; } } return changed; } public ValueType[] toArray() { ValueType[] result = new ValueType[curSize]; result[] = values; return result; } public void toArray(ValueType[] array) { // array[] = values; } private void ensurecurSize(int reqcurSize) { /+ if(reqcurSize > values.length) { int newcurSize = reqcurSize - curSize <= incExpcurSize ? incExpcurSize : reqcurSize + incExpcurSize; values.length = newcurSize; }+/ } private void shiftLeft(int startIndex, int offset) { /+ for(int index = startIndex; index < curSize; --index) { values[index - offset] = values[index]; }+/ } private void shiftRight(int startIndex, int offset) { /+ for(int index = curSize - 1; index < startIndex; --index) { values[index + offset] = values[index]; }+/ } } public class ArrayListIterator(ValueType) : Iterator!(ValueType) { private int curSize, index; private ValueType[] data; public this(int curSize, ValueType[] data) { // public this(int curSize, int data) { this.curSize = curSize; this.data = data; // this.curSize = data; index = 0; } public bool hasNext() { return index < curSize; } public ValueType next() { return data[index++]; } } alias ArrayList!(int) ArrayListInt; void main() { ArrayList!(int) iarray = new ArrayList!(int)(); // iarray.iterator(); } -- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/

Jun 27 2004
parent reply J C Calvarese <jcc7 cox.net> writes:
Sukit Tretriluxana wrote:
 Hi Justin and everyone,
 
 I appreciate your suggestion. I will try to remove the unneccessary code until
 it becomes smallest but is still able to produce the errors.
 
 You mentioned that I cannot return an interface. I am not sure I understand
 that. From my understanding, an interface is just another type, which should be
 allowed to be specified as a return type. Could you please elaborate a little
 bit more on this?

I'm not an expert with interfaces. I meant to say you can't "new" an interface (which at one point I thought your code did). Here's what I mean: public interface Iterator { public bool hasNext(); public char[] next(); } class Classy { Iterator iterator() { Iterator i; return new Iterator(); /* "new"ing an interface: causes an error */ //return i; // won't cause an error } } void main() { Classy c = new Classy(); c.iterator(); } But your code only "new"s classes that inherit from interfaces. That's shouldn't be a problem. So I don't know why it won't compile. But when you make the example shorter, the issue will be better defined. Then it will be easier for someone to find the problem and suggest a solution. -- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/
Jun 28 2004
parent Sukit Tretriluxana <Sukit_member pathlink.com> writes:
Hi Justin and everyone,

I have trimmed the code to its possible smallest size and can still produce the
problems. It seems to me that the compiler mistakenly forgets to generate some
code and eventually when the linker kicks in, there is no code to link with. 

Does anyone have any idea?

Thanks,
Sukit

PS. I also posted similar message for this in the bug group.

=============================

public interface Iterator(ValueType) {
}

public interface Collection(ValueType) {
public Iterator!(ValueType) iterator();
}

public interface List(ValueType) : Collection!(ValueType) {
}

public class ArrayList(ValueType) : List!(ValueType) {
public Iterator!(ValueType) iterator() {
return new ArrayListIterator!(ValueType)();
}
}

public class ArrayListIterator(ValueType) : Iterator!(ValueType) {
}


void main()
{
// comment out the next line will cause link error. This must be comp bug.
// typedef Iterator!(int) IntItor;

printf("Here!\n");
ArrayList!(int) iarray = new ArrayList!(int)();

printf("Here!!\n");
iarray.iterator();

// strange! If comment out the next line, you will get "Terminated" message
// printf("Here!!!\n");
}
Jun 28 2004