Thread: Template functions

  1. #1
    Registered User starcatcher's Avatar
    Join Date
    Feb 2008
    Location
    Australia
    Posts
    45

    Question Template functions

    Is it possible to write a function that returns a variable type? My guess would have been to use template functions, although the rest of my program is in C (I have a mixed C/C++ programming environment so I can still use C++ in parts). The following (unrelated) code snippet works for example:
    Code:
    template <typename T> void Swap(T *Ptr_A,T *Ptr_B)
    {
    	// Declare variables
    	T Temp;
    
    	// Perform swap
    	Temp=*Ptr_A;
    	*Ptr_A=*Ptr_B;
    	*Ptr_B=Temp;
    }
    but when I try something like this it doesn't work:
    Code:
    template <typename T> T Comb_C(int M,int R)
    {
    	// Declare variables
    	T Answer=1;
    
    	// Work out mCr
    	for(int i=1;i<=R;i++)
    	{
    		Answer*=(M+1)-i;
    		Answer/=i;
    	}
    
    	// Return answer
    	return Answer;
    }
    The compiler tells me:
    error LNK2019: unresolved external symbol "int __cdecl Comb_C<int>(int,int)" (??$Comb_C@H@@YAHHH@Z) referenced in function _main
    when I do
    Code:
    Comb_C<int>(a,b)
    I have declared the function, in exactly the same way I had declared the swap function, so I must assume that that isn't the problem.
    I do realise that something like this would work IF I only need the different types to be different types of int (int8,int16,int32,int64) OR diff. types of floating point (float,double):
    Code:
    #define COMB_C(T,M,R)          ((T) Comb_C((M),(R)))
    ...
    int main()
    {
        ...
        printf("%d\n",COMB_C(__int32,12,4));
        ...
    }
    ...
    __int64 Comb_C(int M,int R)
    {
        __int64 Answer=1;
        for(int i=1;i<=R;i++)
        {
            Answer*=(M+1)-i;
            Answer/=i;
        }
        return Answer;
    }
    Is there a way to do it with template functions though, where I could theoretically have the output as an integer or double or whatever?

    Thx,
    Philipp

  2. #2
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    This should be in the C++ section, not the C section.

  3. #3
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Your templated code should work OK. If the linker can't find the function there may be typos or problems with how your project is set up.

    Could you post a complete example that produces this error?

    For example
    Code:
    #include <iostream>
    
    template <typename T>
    T foo(int n);
    
    
    int main()
    {
        char c = foo<char>(100);
        int i = foo<int>(1278);
        unsigned f = foo<unsigned>(-1);
        std::cout << c << " " << i << " " << f << '\n';
    }
    
    template <typename T>
    int foo(int n)
    {
        return T(n);
    }
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  4. #4
    Registered User starcatcher's Avatar
    Join Date
    Feb 2008
    Location
    Australia
    Posts
    45

    Question Complete code example with errors

    Aren't you sure that the second red one (int) shouldn't be T?
    Anyway, I've been experimenting around with what works and what doesn't and I have put together this program which demonstrates that. Note though that this code excerpt deals simply with template functions and not with the special case of template function for which I asked for help. As it turned out, the other template functions didnt work either. How can I fix it up this code so that the template functions Swap_B and Swap_C work properly?
    Code:
    // C Board Ex.cpp : Defines the entry point for the console application.
    // Programming Environment: Microsoft Visual Studio 6.0 (Visual C++ in this case)
    
    // Includes
    #include "stdafx.h" // Contains statements: #pragma once, #include <iostream> and #include <tchar.h>
    #include "Swap.h"
    
    // Functions
    template <typename T> void Swap_A(T *Ptr_A,T *Ptr_B);
    
    // Main function
    int main(void)
    {
    	// Declare variables
    	int a,b;
    	double A=1.1,B=2.2;
    
    	// Test functions
    	Other_Function(&a,&b); // Fine: Was declared in header at file scope and so extern was unnecessary. Assigns values 1 to a and 2 to b.
    	printf("a=%d b=%d A=%3f B=%f\n",a,b,A,B);
    	Swap_A<int>(&a,&b); // Fine: Local function which proves that template functions work in my programming environment. Swaps values of a and b
    	Swap_A<double>(&A,&B); // Fine: Ditto. Swaps values of A and B
    	printf("a=%d b=%d A=%3f B=%f\n",a,b,A,B);
    	Swap_B<int>(&a,&b); // Fine: <int> version of Swap_B was specifically called in Swap.cpp in Other_Function() and so no error occurs. Why?? If that function call is commented then this comes up as an error too.
    	Swap_B<double>(&A,&B); // Error LNK2019: unresolved external symbol "void __cdecl Swap_B<double>(double *,double *)" (??$Swap_B@N@@YAXPAN0@Z) referenced in function _main
    	printf("a=%d b=%d A=%3f B=%f\n",a,b,A,B);
    	Swap_C<int>(&a,&b); // Error LNK2019: unresolved external symbol "void __cdecl Swap_C<int>(int *,int *)" (??$Swap_C@H@@YAXPAH0@Z) referenced in function _main
    	Swap_C<double>(&A,&B); // Error LNK2019: unresolved external symbol "void __cdecl Swap_C<double>(double *,double *)" (??$Swap_C@N@@YAXPAN0@Z) referenced in function _main
    	printf("a=%d b=%d A=%3f B=%f\n",a,b,A,B);
    
    	// Delay exit
    	printf("Press enter to exit!");
    	fgetc(stdin);
    
    	// Return a value
    	return 0;
    }
    
    // Swap function
    template <typename T> void Swap_A(T *Ptr_A,T *Ptr_B)
    {
    	// Perform swap
    	T Temp=*Ptr_A;
    	*Ptr_A=*Ptr_B;
    	*Ptr_B=Temp;
    }
    // EOF
    
    
    
    // Swap.cpp : Contains Swap_B function
    //
    
    // Includes
    #include "stdafx.h"
    #include "Swap.h"
    
    // Functions
    template <typename T> void Swap_B(T *Ptr_A,T *Ptr_B)
    {
    	// Perform swap
    	T Temp=*Ptr_A;
    	*Ptr_A=*Ptr_B;
    	*Ptr_B=Temp;
    }
    template <typename T> void Swap_C(T *Ptr_A,T *Ptr_B)
    {
    	// Perform swap
    	T Temp=*Ptr_A;
    	*Ptr_A=*Ptr_B;
    	*Ptr_B=Temp;
    }
    void Other_Function(int *a,int *b)
    {
    	*a=2;
    	*b=1;
    	Swap_B<int>(a,b); // Call Swap_B function but not Swap_C function to see the difference that makes
    }
    // EOF
    
    
    
    // Swap.h : Declares Swap_B function
    //
    
    // Ensure that code is only executed once
    #ifndef SWAP_H
    #define SWAP_H
    
    // Functions
    template <typename T> extern void Swap_B(T *Ptr_A,T *Ptr_B);
    template <typename T> extern void Swap_C(T *Ptr_A,T *Ptr_B);
    void Other_Function(int *a,int *b);
    
    // Endif
    #endif /*SWAP_H*/
    // EOF
    I think that what i am doing is aptly described by the comments. I coloured the important parts to make them easier to find. If there is anything else that you need to know, please just ask. I can't explain what's going on...

    Thx,
    Philipp
    I program solely as a hobby so this is definitely not homework.
    Best thing that's been said to me:
    I was so pleasantly surprised to see another post in this thread, and yours was brilliant; a fitting end to a subject (matrix manipulations of all kinds) that is quite intriguing.
    Read this thread to find out why...
    Cannibalism

  5. #5
    Registered User starcatcher's Avatar
    Join Date
    Feb 2008
    Location
    Australia
    Posts
    45
    I realise now that ur code was supposed to produce an error so forget my very first sentence! (only) lol!
    I program solely as a hobby so this is definitely not homework.
    Best thing that's been said to me:
    I was so pleasantly surprised to see another post in this thread, and yours was brilliant; a fitting end to a subject (matrix manipulations of all kinds) that is quite intriguing.
    Read this thread to find out why...
    Cannibalism

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User starcatcher's Avatar
    Join Date
    Feb 2008
    Location
    Australia
    Posts
    45
    Thank you. That helped a lot.

    Philipp
    I program solely as a hobby so this is definitely not homework.
    Best thing that's been said to me:
    I was so pleasantly surprised to see another post in this thread, and yours was brilliant; a fitting end to a subject (matrix manipulations of all kinds) that is quite intriguing.
    Read this thread to find out why...
    Cannibalism

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Function template has already been defined
    By Elysia in forum C++ Programming
    Replies: 19
    Last Post: 04-14-2009, 10:17 AM
  2. Polynomials and ADT's
    By Emeighty in forum C++ Programming
    Replies: 20
    Last Post: 08-19-2008, 08:32 AM
  3. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  4. using Template Functions
    By ashcan1979 in forum C++ Programming
    Replies: 3
    Last Post: 09-20-2006, 12:44 AM
  5. Friend template functions
    By lyx in forum C++ Programming
    Replies: 4
    Last Post: 10-02-2003, 01:11 PM