VS.NET 7.1 Internal compiler error on inline template method??

D

dilip ranganathan

Hi

I have taken the liberty to cross-post this. It appeared on c.l.c++.m
but the ICE is regarding VS.NET 7.1 C++ compiler.

post follows:

==============================================
John said:
Thus, I suggest you send the smallest example that fails to compile
(or a link to it)

John,

Thank you for the response. We've managed to capture a small snippet
of
code that generates the Internal compiler error. It is as follows:

#include <memory>

class Key { };

class NullKey : public Key { };

class SortList { };

template <typename T> class SortOrder : public SortList {
public:
SortOrder() { }
};


class obj { typedef NullKey KeyType; };


class PersistenceManager {
//public:
// PersistenceManager() { }
public:
template <typename T> void loadSet(const Key &key = NullKey(),
const SortOrder<T>
&sort =
SortOrder<T>());
};



template <typename T>
void PersistenceManager::loadSet(const Key &key,
const SortOrder<T> &sort) {

}

void main() {
PersistenceManager pm;
pm.loadSet<obj>();
}

Beyond this, if the default constructor for PersistenceManager is
uncommented, the INTERNAL COMPILER ERROR disappears and is replaced by
a
standard compiler error, which also does not make sense:

d:\Documents and Settings\mpetter\My
Documents\Projects\test2\test2.cpp(25): error C2440: 'default
argument' :
cannot convert from 'SortOrder<T>' to 'const SortOrder<T> &'
with
[
T=obj
]


If the compiler can convert the NullKey to a const NullKey &, why
can't it
do the same for SortOrder<T>? They are parallel cases, except that
SortOrder is templated.


Furthermore, both the INTERNAL COMPILER ERROR and the conversion error
can
be alleviated by moving the function's implementation inline into the
class
declaration as shown in Figure 2:

Figure 2: Error-free Code:
----------------------------------------------------------------------------------------------------------------------------

#include <memory>


class Key { };

class NullKey : public Key { };


class SortList { };

template <typename T> class SortOrder : public SortList {
public:
SortOrder() { }
};


class obj { typedef NullKey KeyType; };


class PersistenceManager {
//public:
// PersistenceManager() { }
public:
template <typename T> void loadSet(const Key &key = NullKey(),
const SortOrder<T>
&sort =
SortOrder<T>())//;
{ }
};



/*template <typename T>
void PersistenceManager::loadSet(const Key &key,
const SortOrder<T> &sort) {

}*/



void main() {
PersistenceManager pm;
pm.loadSet<obj>();
}

----------------------------------------------------------------------------------------------------------------------------

Any explanations to this erratic behavior are appreciated.

Thanks again.

John
================================================

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
F

Francis Glassborow

dilip said:
void main() {
PersistenceManager pm;
pm.loadSet<obj>();
}

I think your real problem is probably a compiler one, but you also have
an error that all the compilers I have tried identify; main returns int.
Once a compiler has accepted void main() it is free to do anything it
likes because it is no longer in conforming C++ mode.


--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
P

Patrick Kowalzick

Hi all,
Thank you for the response. We've managed to capture a small snippet
of
code that generates the Internal compiler error. It is as follows:

[snip]

Hard to follow, so I stripped it a little bit:


// ********** CODE START **************
template <typename T>
class SortOrder {};

class PersistenceManager
{
public:
//PersistenceManager() { } // (1)
template <typename T>
void loadSet(const SortOrder<T> &sort = SortOrder<T>() ); // (2)
};

template <typename T> inline
void PersistenceManager::loadSet(const SortOrder<T> &sort) {} // (3)

int main()
{
PersistenceManager pm;
pm.loadSet<int>();

return 0;
}
// ********** CODE END **************

-This code here is still bailing out with internal compiler error.

-Uncommenting (1) results in:
error C2514: 'SortOrder<T>' : class has no constructors
funny :)

-moving the default arguments from (2) to (3) - voilà, it compiles
(I have to look in the standard)
same with or without (1)

Regards,
Patrick



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
P

Patrick Kowalzick

Ups sorry, next post.

I was able to strip even further still getting an internal compiler error:


template <typename T> class CFoo {};

template <typename T> void foo( CFoo<T> = CFoo<T>() );
template <typename T> void foo( CFoo<T> ) {}; // <----watch this semicolon

int main()
{
foo<int>();
return 0;
}

removing the semicolon results in a differnt error message (LOL):
'CFoo<T>' : class has no constructors
which I mentioned in the other posting.

putting the default argument in the function body works fine (g++ refuses
this), as well as simple overloading. The first case should not work in my
opinion regarding:
"8.3.6 Default arguments
4
For non-template functions, default arguments can be added in later
declarations of a function in the same scope."
Hmm, not 100% but nearly. Seems MS is wrong.

Another interessting cite (obviously more important):
"14.7.1 Implicit instantiation
11
If a function template f is called in a way that requires a default argument
expression to be used, the dependant names are looked up, the semantics
constraints are checked, and the instantiation of any template used in the
default argument expression is done as if the default argument expression
had been an expression used in a function template specialization with the
same scope, the same template parameters and the same access as that of the
function template f used at that point. This analysis is called default
argument instantiation. The instantiated default argument is then used as
the argument of f."

what means IMO that MSVC has a small bug.

That would mean for the OP, if there are no doubts, put the function inline
inside the class and you are fine with most of the compilers.

Regards,
Patrick



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top