[英]Linker error for recursive calls to variadic function
我已經仔細閱讀了可變參數模板的鏈接器錯誤,但似乎無法解決我的問題。
我有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.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樣式varargs的函數。 我不知道您想看到什么,因為您在代碼中都不使用模板varargs!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.