2013-04-25 40 views
9

當我嘗試編譯下面的代碼時,出現鏈接器錯誤:Undefined symbols for architecture x86_64: "Foo()", referenced from: _main in main.o使用LLVM 4.2。未定義constexpr函數的符號

此功能僅在功能標記爲constexpr時發生。當功能標記爲const時,程序將正確編譯和鏈接。爲什麼聲明函數constexpr會導致鏈接器錯誤?

(我知道寫的函數這種方式不給編譯時計算的好處。在這一點上我很好奇,爲什麼函數失敗鏈接)

的main.cpp

#include <iostream> 
#include "test.hpp" 

int main() 
{ 
    int bar = Foo(); 
    std::cout << bar << std::endl; 

    return 0; 
} 

test.hpp

constexpr int Foo(); 

TEST.CPP

#include "test.hpp" 

constexpr int Foo() 
{ 
    return 42; 
} 
+0

見http://stackoverflow.com/questions/14391272/does-constexpr-imply-inline – 2013-04-25 16:12:47

回答

8

Why does declaring the function constexpr cause a linker error?

這是因爲constexpr函數隱inline。每個段落的C++標準11 7.1.5/2:

A constexpr specifier used in the declaration of a function that is not a constructor declares that function to be a constexpr function. Similarly, a constexpr specifier used in a constructor declaration declares that constructor to be a constexpr constructor. constexpr functions and constexpr constructors are implicitly inline (7.1.2).

每個段落7.1.2/4,則:

An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case (3.2). [...]

+0

'inline'不會對聯動任何影響。 (這可能是'constexpr',因爲它與const之間的關係一般,但是在你引用的部分中沒有任何內容可以表明這一點。) – 2013-04-25 16:15:00

+0

@JamesKanze:編輯,謝謝 – 2013-04-25 16:20:02

+0

@JamesKanze:7.1.5說「The 'constexpr'說明符對constexpr函數或constexpr構造函數的類型沒有任何影響。「和(語言)聯繫是功能類型(7.5)的一部分。所以這似乎限制了「constexpr」對連接的任何影響。 – 2016-01-27 16:57:50

1

這是一個有趣的問題。如Andy Prowl所述,constexpr使 函數inline,這意味着在使用它的每個翻譯單元中必須有 的定義; 我會期待編譯器的錯誤。 (其實,如果 我正確讀取§3.2/ 5,如果你使用 功能並沒有定義的診斷是必需的。)

至於爲什麼const有不同的行爲:你不能標記 非-menber功能const。如果你寫const int Foo();, 它不是爲const的功能,但類型,它返回 (但如果返回類型不是一個類類型, cv修飾符被忽略,所以這是真的一樣int Foo();) 。

5

constexpr函數的主體必須在其使用的每個點都可見。在你的情況下,你必須move Foo()的代碼爲test.hpp

例如,在main.cpp考慮下面的代碼:

constexpr int Foo(); 

int main() { 
    static_assert(Foo() == 42, "Ops"); 
} 

其中Foo()test.cpp定義。如果編譯器無法看到Foo()確實返回42,應如何檢查static_assert條件,同時處理main.cpp。這不可能。 constexpr函數的全部意義在於編譯器可以在編譯時「調用」它們,爲了實現這一點,它必須看到代碼。

因此,該編譯罰款:

constexpr int Foo() { return 42; } 

int main() { 
    static_assert(Foo() == 42, "Ops"); 
} 
+0

+1感謝提到'static_assert'。這使得我的問題的原因更加明顯。 – Aurelius 2013-04-25 16:55:42