簡體   English   中英

遞歸調用可變參數函數的鏈接器錯誤

[英]Linker error for recursive calls to variadic function

我已經仔細閱讀了可變參數模板的鏈接器錯誤,但似乎無法解決我的問題。

我有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.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM