Function Templates

My problem is the following

I'm using MSVC 6.0

I have a function template

template < typename A, typename B, typename C >
void function( const C parameter )
{
  // function that uses instances of class A, B and C
}

and suppose i have a class that calls in 3 different methods

void MyClass::Function1()
{
  ClassC parameter;
  function< ClassA, ClassB >( parameter );
}

void MyClass::Function2()
{
  ClassF parameter;
  function< ClassD, ClassE >( parameter );
}

void MyClass::Function3()
{
  ClassI parameter;
  function< ClassG, ClassH >( parameter );
}

but every time I call Function1 or Function2

it calls the "function" template with ClassG, ClassH and ClassI as parameters...

in order to sum up

instead of calling the template function with the parameters set in its invocation, it calls it with the parameter of the invocation that appears last in the module

any idea of why this happens? and how to solve it?
(I know how to solve my problem in another way, but i want to understand why this doesnt work and how to make it work)
LVL 9
tinchosAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

skianCommented:
I see nothing worng : in the output of the program
below is :

function<A,B>(C)
function<D,E>(F)
function<G,H>(I)

which is, I think, the expected behaviour.

(well, I use gcc (on linux) instead of vc++6 but
vc++ can't be THAT broken...)

Are you sure you ACTUALLY call Function1 & Function2 ?

Stephane
-----

#include <stdio.h>

class ClassA { public: char *p() const { return "A"; } };
class ClassB { public: char *p() const { return "B"; } };
class ClassC { public: char *p() const { return "C"; } };
class ClassD { public: char *p() const { return "D"; } };
class ClassE { public: char *p() const { return "E"; } };
class ClassF { public: char *p() const { return "F"; } };
class ClassG { public: char *p() const { return "G"; } };
class ClassH { public: char *p() const { return "H"; } };
class ClassI { public: char *p() const { return "I"; } };
class MyClass {
public:
     void MyClass::Function1();
     void MyClass::Function2();
     void MyClass::Function3();
};

template < typename A, typename B, typename C >
void function( const C parameter )
{
 // function that uses instances of class A, B and C
A a;
B b;
printf("function<%s,%s>(%s)\n", a.p(), b.p(), parameter.p());
}

void MyClass::Function1()
{
 ClassC parameter;
 function< ClassA, ClassB >( parameter );
}

void MyClass::Function2()
{
 ClassF parameter;
 function< ClassD, ClassE >( parameter );
}

void MyClass::Function3()
{
 ClassI parameter;
 function< ClassG, ClassH >( parameter );
}

main() {
     MyClass obj;
     obj.Function1();
     obj.Function2();
     obj.Function3();
}
0
burcarpatCommented:
this compiles and runs fine under msvc6 sp5 and doesn't have the problem you mentioned.  i suspect there is actually another problem there.  are ClassA, B, C, etc. are in a hierarchy somehow?

--- cut from here ---
template <
  typename A,
  typename B,
  typename C
>
void
function(const C parameter) {
     std::cout << A::value << " " << B::value << " " << C::value << std::endl;
}; // function


class ClassA { public: enum { value = 1 }; };
class ClassB { public: enum { value = 2 }; };
class ClassC { public: enum { value = 3 }; };
class ClassD { public: enum { value = 4 }; };
class ClassE { public: enum { value = 5 }; };
class ClassF { public: enum { value = 6 }; };
class ClassG { public: enum { value = 7 }; };
class ClassH { public: enum { value = 8 }; };
class ClassI { public: enum { value = 9 }; };


class MyClass {
public:

  void
  Function1() {
    ClassC parameter;
    function< ClassA, ClassB >( parameter );
  };

 
  void
  Function2() {
    ClassF parameter;
    function< ClassD, ClassE >( parameter );
  }

 
  void
  Function3() {
    ClassI parameter;
    function< ClassG, ClassH >( parameter );
  };

}; // MyClass


int
main(int argc, char* argv[]) {

  MyClass mc;

  mc.Function1();
  mc.Function2();
  mc.Function3();

  return 0;
}; // main
--- cut from here ---
0
burcarpatCommented:
ooops, sorry skian, didn't see your post...
0
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

tinchosAuthor Commented:
you're right,but trying to simplify my question, i skipped something

the template arguments to be deduced from the parameters are 2

trying this

---------------------------------------------------------
// Cut from here
template < typename A, typename E , typename F  >
void
function(const E parameter, const F parameter2)
{
    std::cout << A::value << " " << E::value << " " << F::value << std::endl;
}; // function


class ClassA { public: enum { value = 1 }; };
class ClassB { public: enum { value = 2 }; };
class ClassE { public: enum { value = 5 }; };
class ClassF { public: enum { value = 6 }; };


class MyClass
{
public:

 void
 Function1() {
   ClassE parameter;
   ClassF parameter2;
   function< ClassA>( parameter, parameter2 );
 };

 
 void
 Function2() {
   ClassE parameter;
   ClassF parameter2;
   function< ClassB>( parameter, parameter2 );
 }

}; // MyClass


int
main(int argc, char* argv[]) {

 MyClass mc;

 mc.Function1();
 mc.Function2();

 return 0;
}; // main
// Cut to here

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

the output should be  

1 - 5 - 6
2 - 5 - 6

but the output is

2 - 5 - 6
2 - 5 - 6

(always with the values of the last call)

this is the real problem
0
burcarpatCommented:
this is clearly a bug.  in fact, no need for MyClass at all.  add

    ClassE parameter;
    ClassF parameter2;

    function<ClassA>( parameter, parameter2 );
    function<ClassB>( parameter, parameter2 );

in your main() instead and then play with the order of the function call and you get the same thing.  obviously, template deduction does not work correctly.  gcc and bcc handles this w/o any problems.  i suspect msvc7 would also take care of it.  unfortunately, msdn does not seem to have a report or a fix for this issue for msvc6

note that, this works correctly:

--- cut from here ---
template <
  typename A,
  typename E,
  typename F
  >
A
function(const E  parameter,
         const F  parameter2) {
  std::cout << A::value << " " << E::value << " " << F::value << std::endl;
  return A();
}; // function
--- cut from here ---

which goes to show that, this is probably a problem with the name mangling in msvc6 'cause when A is given as the result type, although the compiler will still need an explicit instantiation to deduce it ( as in function<ClassA> and function<ClassB> ), this time it manages to differentiate successfully

if the return value is not important, a quick fix for this problem can be this:

--- cut from here ---
template <
  typename A,
  typename E,
  typename F
  >
A*
function(const E  parameter,
         const F  parameter2) {
  std::cout << A::value << " " << E::value << " " << F::value << std::endl;
  return NULL;
}; // function
--- cut from here ---

this basically forces msvc6 to take the result type into account by forcing it to be included in the mangled function name but does nothing with it and msvc6 will probably successfully optimize the return value away in most of the cases

in general, i would suggest switching to msvc7.1 for any serious template-based code development.  mcvc6 is terrible with templates and you'll have many more problems like this in the future
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
tinchosAuthor Commented:
ok, you're right

as you say, in msvc 7 is solved

thanks a lot
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.