C ++模板未解析的外部

时间:2014-08-24 11:54:49

标签: c++ templates overloading

我有一个非常简单的问题。

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);
}

我使用的是Visual Studio 2012,红色下划线没有任何内容。我尝试编译,但它给了&#34; 1未解析的外部&#34;错误。

4 个答案:

答案 0 :(得分:4)

代码存在两个问题。

首先,main函数不应该是模板。您只需删除template

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

其次,您将临时传递为non-const引用。这是not allowed。您可以尝试更改添加const的模板函数签名:

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

(好吧,VS 有时候允许non-const引用临时绑定,虽然它不应该。但也许不是你的情况。)


此外,function可能会与std::function发生冲突。考虑重命名。

答案 1 :(得分:2)

main函数无法模板化:

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

答案 2 :(得分:0)

您无法模拟main()函数,因为它是程序的入口点。但是,如果要模板化另一个函数,语法非常简单:

#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);
}

答案 3 :(得分:0)

虽然你已经得到了许多包含正确信息的答案,但是没有一个答案解决了我看起来像底层问题的问题:你的程序如何编译/链接,但是IDE没有用红色下划线表示错误?

答案很简单:您编写的代码不包含任何实际错误。它只是不完整。

尽管如此,这可能并没有多大帮助。要理解它,您可能需要更多地了解开发工具如何协同工作以生成程序。

尽管您可能还没有使用过大型项目(如果有的话),除了最小的程序之外,将代码分解为多个文件是相当典型的。在这种情况下,这些文件中的一个(且仅一个)将包含main函数。其余包含其他代码 - 函数定义,类定义等。其中每一个都可以独立编译(假设代码编写正确)。然后,当它们全部被编译时,链接器会运行以将这些部分组合成一个完整的程序。

目前看来,您的代码正在正确编译。只有当它到达那个连接阶段时才会崩溃。如上所述,原因很简单:因为您的程序不完整。具体要求是(§3.6.1/ 1):

  

程序应包含一个名为main的全局函数,它是程序的指定开始。

现在,您可能会(非常正确地)指出您的代码 包含您打算用作程序开头的main。这个问题(正如其他人指出的那样,但没有一个直接说明)是,虽然你已经定义了名为main某事,但你所定义的是不是一个功能 - 它是一个功能模板。函数模板本身不是函数 - 它是一段代码,可以在实例化时生成模板。

实例化模板时,实例化非常明显:

std::vector<int> data;

对于函数模板,实例化通常不太明显 - 您定义了一个函数模板,然后调用就像是一个函数一样。编译器根据您传递的参数类型,选择要使用的模板参数。

虽然有一个限制:要弄清楚函数调用中传递的参数类型,编译器必须“看到”函数模板(源代码到)调用该函数模板。然后它可以查看传递的参数类型,将它们替换为模板参数,并根据它们为这些参数创建该函数模板的实例化。

编译器需要查看函数模板本身对该函数模板的调用,将两者放在一起并为该调用创建实际函数。将模板作为函数调用实际上涉及三个步骤:

  1. 检查调用和模板的源代码
  2. 根据传递的参数类型实例化模板
  3. 生成代码以调用正在传递的类型的生成函数
  4. 现在关键点:要调用模板函数,这三个步骤必须按顺序进行。首先,它必须同时查看调用和模板,然后它实例化模板,然后它可以生成代码来调用从模板实例化的函数。不同的调用可能导致模板以不同方式实例化,而(反过来)需要生成不同的代码来调用生成的函数。

    调用main的代码不允许这组步骤。它被预先编译成一个库,因此在编译时,编译器不能考虑任何函数模板 - 它们根本就不存在于那个时间/地点。