?
Solved

Function Templates

Posted on 2003-03-03
6
Medium Priority
?
207 Views
Last Modified: 2010-04-01
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)
0
Comment
Question by:tinchos
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
6 Comments
 
LVL 1

Expert Comment

by:skian
ID: 8058060
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
 
LVL 7

Expert Comment

by:burcarpat
ID: 8058119
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
 
LVL 7

Expert Comment

by:burcarpat
ID: 8058122
ooops, sorry skian, didn't see your post...
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 9

Author Comment

by:tinchos
ID: 8058401
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
 
LVL 7

Accepted Solution

by:
burcarpat earned 300 total points
ID: 8058676
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
 
LVL 9

Author Comment

by:tinchos
ID: 8059010
ok, you're right

as you say, in msvc 7 is solved

thanks a lot
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
Suggested Courses

765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question