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
Click For Summary

Discussion Overview

The discussion revolves around issues related to using templates and non-member functions in C++ within Microsoft Visual Studio. Participants explore how to properly structure template functions across multiple files, particularly focusing on linking errors encountered when attempting to separate function definitions from their declarations.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Exploratory

Main Points Raised

  • One participant shares a code snippet that compiles but results in linker errors when attempting to separate the template function from the main file.
  • Another participant suggests that forward declaring template functions is not appropriate and recommends placing the template definition above the main function.
  • Some participants inquire about the organization of the code across multiple .cpp files and whether they belong to the same project, indicating potential linker issues.
  • It is noted that the entire template function, including its body, typically needs to be in a header file due to the nature of template instantiation.
  • A participant proposes a solution involving explicit template instantiation in a separate .cpp file to avoid including large amounts of code in header files.
  • Concerns are raised about the practicality of including extensive code in header files, with references to the potential for "premature optimization" in structuring code.
  • One participant mentions that their project involves porting and converting code, which influences their approach to organizing templates and functions.

Areas of Agreement / Disagreement

Participants express differing views on the best practices for organizing template functions, with some advocating for header file inclusion while others prefer to keep function definitions out of headers. The discussion does not reach a consensus on the optimal approach.

Contextual Notes

Participants highlight the challenges of linking and instantiation of templates, with some suggesting that the standard practices may not suit all project needs, particularly in cases of code porting.

AlephZero
Science Advisor
Homework Helper
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.
 
Technology news on Phys.org
You don't forward declare template functions. It doesn't make sense. Put the template definition above your main and all should be fine.
 
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...
 

Similar threads

  • · Replies 2 ·
Replies
2
Views
1K
Replies
6
Views
2K
Replies
20
Views
2K
  • · Replies 5 ·
Replies
5
Views
2K
  • · Replies 6 ·
Replies
6
Views
12K
Replies
63
Views
6K
  • · Replies 5 ·
Replies
5
Views
3K
Replies
1
Views
2K
  • · Replies 15 ·
Replies
15
Views
3K
  • · Replies 13 ·
Replies
13
Views
2K