简体   繁体   中英

C++ Templating Unresolved Externals

I have a very simple question.

template<class Type, class Type2>
void function(Type & a, Type2 & b)
{
    cout << a << " " << b << endl;
}

template<class Type, class Type2>
int main()
{
    function(1, 2.0);
}

I am using Visual Studio 2012, nothing is underlined with red. I try to compile but it gives "1 unresolved external" error.

There are two issues with the code.

Firstly, main function is not supposed to be a template. You can just remove the template line

template<class Type, class Type2>
int main()

Secondly, you are passing temporaries as non-const references. This is not allowed . You may try to change template function signature adding const :

void function(const Type & a, const Type2 & b)

(Well, VS sometimes allows non-const reference to temporary binding, although it should not. But perhaps not in your case anyway.)


In addition, function may collide with std::function . Consider renaming.

main function can't be templated:

int main()
{
    function(1, 2.0);
}

You can't template the main() function, as it is the entry point to the program. However, if you want to template another function the syntax is pretty straightforward:

#include <iostream>

template<class Type, class Type2>
void function(Type a, Type2 b)
{
    std::cout << a << " " << b << std::endl;
}


int main()
{      
    function(1, 1);
    function(1, 2.0);
}

While you've gotten a number of answers that contain correct information, none of them has addressed what looks to me like the underlying question: how is it that your program doesn't compile/link, but the IDE doesn't underline anything in red indicating an error?

The answer to that is fairly simple: the code you've written doesn't contain any real errors. It's just incomplete.

That probably doesn't help much by itself though. To understand it, you probably need to understand a little more about how your development tools work together to produce a program.

Although you may not have worked with larger projects much (if at all) yet, in anything but the smallest of programs, it's fairly typical to break your code up into multiple files. In this case, one (and only one) of those files will contain a main function. The rest contain other code--function definitions, class definitions, and so on. Each of those can be compiled independently of the others (assuming the code is written correctly, of course). Then, when they're all compiled the linker runs to put those pieces together into a complete program.

As it stands right now, your code is compiling correctly. It's only when it gets to that linking phase that things fall apart. As noted above, the reason for that is fairly simple: because your program is incomplete. The specific requirement is (§3.6.1/1):

A program shall contain a global function called main, which is the designated start of the program.

Now, you might react by (quite correctly) pointing out that your code does contain a main that you intend to be used as the start of the program. The problem with that (as others have sort of pointed out, but none really stated directly) is that while you've defined something named main , what you've defined is not a function--it's a function template . A function template isn't a function itself--it's a piece of code that can generate a template when you instantiate it.

When you instantiate a class template, the instantiation is fairly visible:

std::vector<int> data;

In the case of function templates, the intantiation is usually less visible--you define a function template, and then make calls as if that were a function. The compiler sorts out what template parameters to use based on the types of the parameters you passed.

There's a limitation to that though: to figure out the types of the parameters that are being passed in the function call, the compiler must "see" both the function template and the (source code to the) call to that function template. Then it can look at the types of the parameters being passed, substitute them for the template parameters, and based on those it creates an instantiation of that function template for those parameters.

The compiler needs to see both the function template itself and the call to that function template to put the two together and create an actual function for that call. Calling the template as a function really involves three steps:

  1. examine the source code to both the call and the template
  2. instantiate the template based on the types of the parameters being passed
  3. generate code to call the generated function for the types being passed

Now comes the crucial point: to call a template function, those three steps have to take place in that order . First it has to look at both the call and the template, then it instantiates the template, then it can generate code to call the function instantiated from the template. Different calls may result in the template being instantiated differently, which (in turn) requires different code to be generated to call the generated function.

The code that calls main doesn't allow that set of steps. It's pre-compiled into a library, so when it's compiled, the compiler can't take any function templates into account--they simply don't exist at that time/place.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM