How Can I Fix Template and Non-Member Function Issues in MS Visual Studio C++?

  • Context: C/C++ 
  • Thread starter Thread starter AlephZero
  • Start date Start date
  • Tags Tags
    C++ Visual
Join the discussion
Registration is free. Ask a follow-up in this thread, or start your own.
6 replies · 5K views
Messages
6,999
Reaction score
299
This little test of templates and non-member functions works fine:

Code:
// test5.cpp : main project file.

#include "stdafx.h"

using namespace System;

	template <class T> void mytest(void);

	int main(array<System::String ^> ^args)
	{
		mytest<double>();
		mytest<int>();
		Console::ReadLine();
		return 0;
	}

	template <class T> void mytest (void)
	{
		T x = 1;
		T y = 2;
		Console::WriteLine("size of T = {0} x/y = {1}",sizeof(T),x/y);
	}

I want to split this up so function mytest is in its own .cpp file, but I can't get it to work.

It compiles OK but I get
Code:
test5.obj : error LNK2028: unresolved token (0A000006) "void __cdecl mytest<int>(void)" (??$mytest@H@@$$FYAXXZ) referenced in function "int __clrcall main(cli::array<class System::String ^ >^)" (?main@@$$HYMHP$01AP$AAVString@System@@@Z)
test5.obj : error LNK2028: unresolved token (0A000007) "void __cdecl mytest<double>(void)" (??$mytest@N@@$$FYAXXZ) referenced in function "int __clrcall main(cli::array<class System::String ^ >^)" (?main@@$$HYMHP$01AP$AAVString@System@@@Z)
test5.obj : error LNK2019: unresolved external symbol "void __cdecl mytest<int>(void)" (??$mytest@H@@$$FYAXXZ) referenced in function "int __clrcall main(cli::array<class System::String ^ >^)" (?main@@$$HYMHP$01AP$AAVString@System@@@Z)
test5.obj : error LNK2019: unresolved external symbol "void __cdecl mytest<double>(void)" (??$mytest@N@@$$FYAXXZ) referenced in function "int __clrcall main(cli::array<class System::String ^ >^)" (?main@@$$HYMHP$01AP$AAVString@System@@@Z)
which suggests it doesn't realize it has to instantiate the templates.

What am I doing wrong? FWIW changing "class T" to "typename T" makes no difference.
 
Physics news on Phys.org
AlephZero said:
I want to split this up so function mytest is in its own .cpp file, but I can't get it to work.

I guess you have (two) different cpp files, each containing part of the code? Are both parts of the same project? Perhaps linker has no idea where to look for the compiled code.
 
Usually you are forced to put the entire template function (including body) in a header file.
This is necessary since the expansion into code only takes place when it's actually used.
Just like an old style C macro.
 
Borek said:
I guess you have (two) different cpp files, each containing part of the code? Are both parts of the same project? Perhaps linker has no idea where to look for the compiled code.

Yes the two files are part of the same project.

I like Serena said:
Usually you are forced to put the entire template function (including body) in a header file.
This is necessary since the expansion into code only takes place when it's actually used.
Just like an old style C macro.

Yes ... (as with DH's reply) ... except this will finish up as a big library of non-class functions, and the idea of including maybe 106 lines of code in header file(s) doesn't seem the right way to go, and neither does creating an intricate logical structure to dissect it into smaller pieces.

Actually, I've stumbled across a reasonably good solution in the MS documentation. You can explicitly instantiate a template function like this:

Code:
// file mytest.cpp

template <class T> void mytest (void);

template void mytest <int> (void);
template void mytest <double> (void);

template <class T> void mytest (void)
	{
		T x = 1;
		T y = 2;
		Console::WriteLine("size of T = {0} x/y = {1}",sizeof(T),x/y);
	}

And then call them in another file.

That will probably work OK for me, because most of the time I know in advance what classes I want to instantiate, and it will keep the function definitions out of the header files.

Thanks all.
 
Last edited:
AlephZero said:
Yes ... (as with DH's reply) ... except this will finish up as a big library of non-class functions, and the idea of including maybe 106 lines of code in header file(s) doesn't seem the right way to go, and neither does creating an intricate logical structure to dissect it into smaller pieces.
What makes you think you will get 106 lines of code in header files? I think this is a case of premature optimization. "Premature optimization is the root of all evil (or at least most of it) in programming." (Donald Knuth). Don't worry about problems that don't exist.

The standard approach with templates is to put them into headers. When you do that, you typically declare your free function templates as inline.
 
D H said:
What makes you think you will get 106 lines of code in header files?

It's a code porting (and language conversion) project, so I know where I'm starting from. And as with most "computer archeology" type projects, that isn't the place one would want to start from given a free choice...