2013-04-25 13 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 –

उत्तर

8

Why does declaring the function constexpr cause a linker error?

है ऐसा इसलिए है क्योंकि constexpr कार्यों परोक्ष inline हैं। प्रति पैरा सी ++ 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' सामान्य रूप से कॉन्स के साथ अपने रिश्ते को देखते हैं, लेकिन उस खंड में कुछ भी नहीं है जिसे आप उद्धृत करते हैं जो यह इंगित करेगा।) –

+0

@ जेम्ससांज: संपादित, धन्यवाद –

+0

@ जेम्ससांज: 7.1.5 कहता है " 'constexpr' विनिर्देशक में कोई कॉन्सएक्स फ़ंक्शन या कॉन्स्टेक्सर कन्स्ट्रक्टर के प्रकार पर कोई ई एफएफ ect नहीं है। " और (भाषा) संबंध एक कार्य के प्रकार (7.5) का हिस्सा है। तो यह लिंक पर 'constexpr' के किसी भी प्रभाव को प्रतिबंधित करने लगते हैं। –

1

यह एक दिलचस्प सवाल है। एंडी प्रोल, constexpr फ़ंक्शन inline बनाता है, जिसका अर्थ है कि प्रत्येक अनुवाद इकाई में इसकी परिभाषा होनी चाहिए; मुझे कंपाइलर से एक त्रुटि की उम्मीद होगी। (वास्तव में, अगर मैं §3.2/5 सही ढंग से पढ़ा, यदि आप फ़ंक्शन का उपयोग करें और वहाँ कोई परिभाषा है एक नैदानिक ​​आवश्यक है।)

क्यों const अलग व्यवहार है करने के लिए के रूप में: आप एक गैर चिह्नित नहीं कर सकते -मेनबर फ़ंक्शन const। आप const int Foo();, लिखते हैं तो यह समारोह जो const है नहीं है, लेकिन प्रकार यह रिटर्न (सिवाय इसके कि यदि वापसी प्रकार एक वर्ग प्रकार नहीं है, सीवी-क्वालिफायर अनदेखी कर रहे हैं, तो यह वास्तव में int Foo(); के समान है) ।

5

constexpr फ़ंक्शन का शरीर हर बिंदु पर दिखाई देना चाहिए जहां इसका उपयोग किया जाता है। आपके मामले में आपको move Foo() का कोड test.hpp पर है।

उदाहरण के लिए, main.cpp में इस कोड पर विचार करें:

constexpr int Foo(); 

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

जहां Foo()test.cpp में परिभाषित किया गया है। main.cpp को संसाधित करते समय संकलक static_assert स्थिति को जांचने के लिए कैसे माना जाता है यदि यह नहीं देख सकता कि Foo()42 लौटाता है। यह असंभव है। constexpr फ़ंक्शंस का पूरा बिंदु यह है कि संकलक संकलन समय पर उन्हें "कॉल" कर सकता है और इसके लिए इसे कोड देखना होगा।

इसलिए, इस ठीक संकलित:

constexpr int Foo() { return 42; } 

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

+1 'static_assert' का उल्लेख करने के लिए धन्यवाद। इससे मेरी समस्या का कारण और अधिक स्पष्ट हो जाता है। – Aurelius

संबंधित मुद्दे