Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么我需要定义一个函数才能将它传递给一个不调用它的模板函数?_C++_Templates_Linker - Fatal编程技术网

C++ 为什么我需要定义一个函数才能将它传递给一个不调用它的模板函数?

C++ 为什么我需要定义一个函数才能将它传递给一个不调用它的模板函数?,c++,templates,linker,C++,Templates,Linker,这个案例比问题的标题更清楚 我有这段代码运行正常。它声明一个函数,然后打印其类型: int f(int); // function receiving int std::cout << "int f(int); type of f = " << typeid(f).name() << std::endl; 我不明白为什么我必须定义这个函数。是否只是因为链接器不够聪明,无法检测到该函数从未在模板化代码中调用?有什么解决方法吗?您正在将函数

这个案例比问题的标题更清楚

我有这段代码运行正常。它声明一个函数,然后打印其类型:

int f(int);  // function receiving int
std::cout << "int f(int); type of f = " << typeid(f).name() << std::endl;

我不明白为什么我必须定义这个函数。是否只是因为链接器不够聪明,无法检测到该函数从未在模板化代码中调用?有什么解决方法吗?

您正在将函数指针传递给另一个函数:模板实例。模板函数的实例本身就是一个函数,它在概念上与任何其他非模板函数没有区别。因此,考虑到这一点:

模板函数不调用指向函数这一事实无关紧要。您正在传递一个指向函数的指针。指针必须指向某个地方。无论它指向什么,都必须存在。指针不用于调用函数这一事实没有任何区别

就像你在某个地方有一个函数,它以一个指向普通
int
的指针作为参数,用一个指向某个
int
的指针来调用它,在某个地方,“
int
某处”必须存在。当你获取某物的地址时,为了产生一个指针,“某物”必须存在。您正在调用的函数永远不会使用该指针读取或更新
int
,这一事实没有任何区别


没有解决办法。这就是C++的工作原理。链接器只“聪明”到可以从一组翻译单元中获取符号引用列表,从另一组翻译单元中获取定义符号列表,并将它们连接在一起。链接器不太可能内置虚拟机来分析链接的每一位代码,以确定某个特定符号是否会在某处实际执行。

您正在将一个函数指针传递给另一个函数:模板实例。模板函数的实例本身就是一个函数,它在概念上与任何其他非模板函数没有区别。因此,考虑到这一点:

模板函数不调用指向函数这一事实无关紧要。您正在传递一个指向函数的指针。指针必须指向某个地方。无论它指向什么,都必须存在。指针不用于调用函数这一事实没有任何区别

就像你在某个地方有一个函数,它以一个指向普通
int
的指针作为参数,用一个指向某个
int
的指针来调用它,在某个地方,“
int
某处”必须存在。当你获取某物的地址时,为了产生一个指针,“某物”必须存在。您正在调用的函数永远不会使用该指针读取或更新
int
,这一事实没有任何区别


没有解决办法。这就是C++的工作原理。链接器只“聪明”到可以从一组翻译单元中获取符号引用列表,从另一组翻译单元中获取定义符号列表,并将它们连接在一起。链接器不太可能内置一个虚拟机来分析链接的每一位代码,以确定某个特定符号是否会在某处实际执行。

模板生成代码。函数模板生成函数。在这种情况下,它生成:

template<>
void PrintDeclarationAndType(std::string text, int(*var)(int))
{
  std::cout << text << typeid(var).name() << std::endl;
}
通过C遗留功能,函数名
f
“衰减”为指向函数的指针:

int f(int);  // function receiving int
PrintDeclarationAndType("int f(int); type of f = ", &f);
现在我希望你看到问题所在;您使用指向
f
的指针,因此指向的函数必须存在

取代

int f(int);  // function receiving int
&f;
但仍然会出现链接器错误


typeid
不是一个函数,它是一个内置运算符。这样就不会生成指针,也不会发生链接器错误。

模板生成代码。函数模板生成函数。在这种情况下,它生成:

template<>
void PrintDeclarationAndType(std::string text, int(*var)(int))
{
  std::cout << text << typeid(var).name() << std::endl;
}
通过C遗留功能,函数名
f
“衰减”为指向函数的指针:

int f(int);  // function receiving int
PrintDeclarationAndType("int f(int); type of f = ", &f);
现在我希望你看到问题所在;您使用指向
f
的指针,因此指向的函数必须存在

取代

int f(int);  // function receiving int
&f;
但仍然会出现链接器错误


typeid
不是一个函数,它是一个内置运算符。因此不会形成指针,也不会发生链接器错误。

谢谢。那么在运行正常的代码段中会发生什么?我假设
typeid
不是一个函数,我没有传递
typeid
指向函数的指针。正确,typeid是在编译时计算的。这与将一个指针传递给一个函数没有什么不同,该函数实际上并不使用该指针,但是,比方说,它的
sizeof
。它不会改变指向的对象必须存在的事实。从理论上讲,编译器可以确定不生成代码以获取对象/函数的指针没有可观察到的效果,并且可以完全优化掉,但是C++不需要编译器这样做,如果它仍然这样做,那就没有办法了。但我的模板函数也会在编译时进行评估。而且
typeid
不需要定义函数。不,模板函数不是“在编译时评估的”。C++不是这样工作的。好的,对不起,是的。它的代码是在编译时生成的,但是计算只是在执行时进行的。谢谢。那么在运行正常的代码段中会发生什么?我假设
typeid
不是一个函数,我没有传递
typeid
指向函数的指针。正确,typeid是在编译时计算的。这与将一个指针传递给一个函数没有什么不同,该函数实际上并不使用该指针,但是,比方说,它的
sizeof
。它不会改变指向的对象必须存在的事实。理论上,编译器可以确定不生成代码