我已经仔细阅读了可变参数模板的链接器错误,但它似乎不能解决我的问题。
我有 3 个文件,detail.h
、detail.cpp
和main.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 样式变量的函数。我不知道你想看到什么,因为你在代码中也没有使用模板!