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

  • C/C++
  • Thread starter AlephZero
  • Start date
  • Tags
    C++ Visual
In summary: I'm in.I suppose I could put the functions into one header file and the class(es) that use them into another, but it's still a bit of a pain.I assume I'm not the first person to run into this, so I'm a bit surprised there isn't a better alternative.In summary, when using templates and non-member functions, it is important to keep all template definitions and declarations in the same header file in order to properly instantiate the templates. Alternatively, explicit instantiation can be used to call the templates in separate files. While it may seem inconvenient to put a large amount of code in a header file, it is the standard approach for templates and premature optimization should be avoided.
  • #1
AlephZero
Science Advisor
Homework Helper
6,982
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
  • #2
You don't forward declare template functions. It doesn't make sense. Put the template definition above your main and all should be fine.
 
  • #3
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.
 
  • #4
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.
 
  • #5
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:
  • #6
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.
 
  • #7
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...
 

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

What is MS Visual Studio C++?

MS Visual Studio C++ is an integrated development environment (IDE) created by Microsoft for programming in the C++ language. It is commonly used by software developers to write, debug, and compile code for various platforms.

How do I solve a problem in MS Visual Studio C++?

To solve a problem in MS Visual Studio C++, you can use the built-in debugging tools, such as breakpoints and watch windows, to identify and fix errors in your code. You can also refer to the documentation or seek help from online forums or communities.

Why does MS Visual Studio C++ show errors in my code?

MS Visual Studio C++ may show errors in your code due to syntax errors, missing libraries, or incorrect settings. It is important to carefully review the error messages and make necessary changes to your code to resolve the errors.

How can I run my code in MS Visual Studio C++?

To run your code in MS Visual Studio C++, you can click on the "Start" button or press the "F5" key on your keyboard. This will compile and execute your code, and the output will be displayed in the "Output" window.

Is MS Visual Studio C++ free?

No, MS Visual Studio C++ is not completely free. There are different versions of the software available, some of which require a license or subscription. However, there is a free version called Visual Studio Community, which can be used for personal and open-source projects.

Back
Top