对可变参数函数的递归调用的链接器错误



我已经仔细阅读了可变参数模板的链接器错误,但它似乎不能解决我的问题。

我有 3 个文件,detail.hdetail.cppmain.cpp个。

detail.h中,只有一行声明一个可变参数函数allSame

//detail.h
bool allSame(unsigned long...);

detail.cpp中,提供了函数的实现。

//detail.cpp
#include "detail.h"
bool allSame() { return true; }
bool allSame(unsigned long first) { return true; }
bool allSame(unsigned long first, unsigned long second) { 
return first == second; 
}
bool allSame(unsigned long first, unsigned long second, unsigned long others...) {
if (first == second)
return allSame(first, others);
else 
return false;
}

正如人们可以很容易地推断的那样,如果函数的可变参数都相同,则函数allSame用于返回。

//main.cpp
#include "detail.h"
#include <iostream>
int main () {
if (allSame(2, 2, 2, 2)) 
std::cout << "All same. " << std::endl;
}

在编译和链接上述三个文件(使用命令g++ detail.cpp main.cpp)时,我收到了这个链接器错误

/disk1/tmp/ccTrBHWU.o: In function `main':
main.cpp:(.text+0x1e): undefined reference to `allSame(unsigned long, ...)'
collect2: error: ld returned 1 exit status

事实上,我没有提供带有特定签名allSame(unsigned long, ...)的重载;但是我确实提供了带有0,1,2,2+(any)参数的函数定义。也许编译器在函数调用时扩展参数包的方式比我想象的更微妙?

[旁注]如果我将detail.cpp的内容移动到detail.h则程序将按预期编译和运行。

您正在声明一个 vararg 函数,但您定义了非 vararg 重载。编译器发出针对 vararg 表单的代码(因为这是可见声明),但链接器无法找到匹配的定义。

要么为非 vararg 表单编写声明,要么编写(定义)一个实际的 vararg 函数,或者最好编写一个可变参数模板(其定义应放在头文件中)。

在 c++ 中,我们可以简单地编写:

template < typename S, typename ... T>
constexpr bool allSame( S first, T ... t ) 
{   
return ((first == t) && ...) ;
}   
int main()
{   
std::cout << allSame( 5,4,3 ) << std::endl;
std::cout << allSame( 10,10,10,10 ) << std::endl;
}   

因此,不再需要将可变参数函数与 varargs 一起使用或使用递归模板。

但是如果你喜欢递归模板,你可以采用这个:

template < typename S, typename ... T>  
constexpr bool allSame( S , T ... );
template <typename FIRST>
constexpr bool allSame( FIRST first ) { return true; }
template < typename FIRST, typename SECOND, typename ... REST>
constexpr bool allSame( FIRST first, SECOND second, REST ... rest )
{   
if ( first != second ) return false;
return allSame( second , rest... );
}   
int main()
{   
std::cout << allSame( 5,4,3 ) << std::endl;
std::cout << allSame( 10,10,10,10 ) << std::endl;
} 

不应使用使用旧 c 样式变量的函数。我不知道你想看到什么,因为你在代码中也没有使用模板!

相关内容

  • 没有找到相关文章

最新更新