Template Arugment Deducing issue With Visual C++ 6

 

One of my team mate was trying to “templatize” the function she wrote. She Immediately came to me and shown a sample piece of code where she failed to get the input from the console window.

The code was as follows

template
void Foo(int nArraySize)
{
T* pArray = new T[nArraySize];
int nIdx;
cout<<”Enter the items to be”<<endl;
for ( nIdx = 0;nIdx < nArraySize;nIdx++)
{
cin>>pArray[nIdx];
}

cout<<”The array contains”<<endl;
for ( nIdx = 0; nIdx < nArraySize;nIdx++)
{
cout<<pArray[nIdx]<<endl;
}
}
int main()
{
int x;
cin >> x;
switch( x )
{
case 1:
Foo( 3 );
break;
case 2:
Foo ( 3 );
break;
default:
break;
}
}

I’m calling the functions from Switch case, not that the type of the argument is not passing. When I compiled the source using Visual C++ 6, I got following error

1
Enter the items
10.233
The array contains
-858993460
0
10

After entering 10.233, error occurred in the stream input. This exits the for loop which reads the elements for the array.

The root cause of this issue is basic_istream::operator << () function replaced with the int version irrelevant to the type of the function we’ve instantiated.


Ok let’s try with more cases to prove the hypothesis add one more switch case

case 3:
Foo ( 3 );
break;.

Now the see the output

1
Enter the items
123.23
The array contains
1
2
3

In the above test, I still tried the float version. Instead compiler still taking inputs as char which is the last instantiation of function inside the switch case.

I believe this as a problem of Microsoft Visual C++ 6 compiler. There’s no meaning in talking about the unsupported compiler and IDE.
Microsoft Corrected this issue in their latest compiler Visual C++ 2008 (not sure about VS 2005 and 2003 )
I also tried the same source code with other compilers like Intel C++ Compiler and Dev C++ compiler. It’s working perfectly fine. The problem is only with the old version of Visual C++ compiler.
Please feel free to share your view points and hypothesises.

 
  • Todd Greer

    This is a known bug in that compiler. The problem was that the mangled name used by the linker did not include template parameters. It only included the function name, argument types, and the return type. Thus when a function template like void foo(int n); gets instantiated, all of the instantiations look the same. They seem to be redundant definitions, so all but one of them get stripped out.

    The standard workaround was to declare the function template as ‘void foo(int n, T* =0)’. Including a T-related type in the argument list makes T get incorporated into the mangled name, making it a T* ensures that there’s no appreciable overhead and that it ha a default value, omitting the name quiets unused parameter warnings, and defaulting the argument keeps it from affecting callers.

    The other standard workaround is to get a better compiler. I’m sure there’s a very good reason the project can’t upgrade compilers; consider carefully whether it’s a good enough reason to justify the pain or using such a poor compiler.

  • http://sarathc.wordpress.com/ S a r a t h

    Thanx Todd Greer. It was a nice explanation and solution for the problem

  • Simon

    Thanks indeed. I just ran into the same problem and that solved it. Good timing!