2012-06-18 18 views
24

मैं एक परियोजना विकसित कर रहा हूं जो कई अंकगणितीय प्रकारों के साथ काम करता है।std नेमस्पेस में <cmath> में कुछ फ़ंक्शन क्यों नहीं हैं?

user_defined_arithmetic.h:

typedef double ArithmeticF; // The user chooses what type he 
           // wants to use to represent a real number 

namespace arithmetic   // and defines the functions related to that type 
{ 

const ArithmeticF sin(const ArithmeticF& x); 
const ArithmeticF cos(const ArithmeticF& x); 
const ArithmeticF tan(const ArithmeticF& x); 
... 
} 

क्या मुझे परेशान कर रहा है यह है कि जब मैं इस तरह कोड का उपयोग करें:

तो मैं इसमें एक शीर्ष, जहां एक उपयोगकर्ता परिभाषित अंकगणित प्रकार के लिए कम से कम आवश्यकताओं को परिभाषित कर रहे हैं बनाया

error: call of overloaded 'sin(ArithmeticF&)' is ambiguous 
candidates are: 
double sin(double) 
const ArithmeticF arithmetic::sin(const ArithmeticF&) 
:
#include "user_defined_arithmetic.h" 

void some_function() 
{ 
    using namespace arithmetic; 
    ArithmeticF lala(3); 
    sin(lala); 
} 

मैं एक संकलक त्रुटि मिलती है

मैंने कभी भी <math.h> शीर्षलेख का उपयोग नहीं किया है, केवल <cmath> है। मैंने हेडर फ़ाइल में using namespace std का कभी भी उपयोग नहीं किया है।

मैं जीसीसी 4.6 का उपयोग कर रहा हूं। *। मैं जाँच की अस्पष्ट घोषणा युक्त हैडर क्या है और यह पता चला है होना करने के लिए:

mathcalls.h:

Prototype declarations for math functions; helper file for <math.h>. 
... 

मुझे पता है, कि <cmath><math.h> हैं, लेकिन यह द्वारा घोषणाओं ढाल चाहिए एसडीडी नेमस्पेस। मैं <cmath> हैडर में खुदाई और पाते हैं:

cmath.h:

... 

#include <math.h> 

... 

// Get rid of those macros defined in <math.h> in lieu of real functions. 
#undef abs 
#undef div 
#undef acos 
... 

namespace std _GLIBCXX_VISIBILITY(default) 
{ 
... 

तो नाम स्थान एसटीडी#include <math.h> बाद शुरू होता है । क्या यहां कुछ गड़बड़ है, या मैंने कुछ गलत समझा?

+2

कुछ बातें पर काम नहीं करता है तो आप पर पुनर्विचार करना चाह सकते हैं जरूरत नहीं: जब अंकगणित प्रकार (अभिन्न प्रकार + डबल + नाव) का उपयोग कर यह आम तौर पर और अधिक कुशल है (और आम) संदर्भ से मूल्य से गुजरने के लिए। एक फ़ंक्शन को कॉल करते समय जिसके लिए आप एक विशिष्ट संस्करण चाहते हैं, 'नामस्थान X' का उपयोग करके' कॉल को अर्हता प्राप्त करें। वैकल्पिक रूप से आप निर्देश * का उपयोग कर * का उपयोग कर सकते हैं ('अंकगणित :: पाप' का उपयोग कर)। आखिरकार 'टाइपपीफ' संपादित करके बदलते प्रकारों का पूरा दृष्टिकोण वास्तव में एक बुरा विचार है। –

+0

@ डेविड रोड्रिगेज-ड्राईबीस: धन्यवाद! कृपया, क्या आप मुझे एक वैकल्पिक समाधान संकेत दे सकते हैं? मैं संदर्भ द्वारा पास का उपयोग कर रहा हूं, क्योंकि संख्या एक कस्टम प्रकार हो सकती है। इसका मतलब है कि यह कुछ किलोबाइट भी बड़ा हो सकता है। मैं उम्मीद कर रहा था कि जब मैं कार्यों को रेखांकित करता हूं और इनलाइन के अंदर std प्राथमिक कार्यों का उपयोग करता हूं, तो कोई नुकसान नहीं किया जाएगा। या होगा? क्या आप मुझे कुछ सुझाव दे सकते हैं? –

+0

@ डेविड रोड्रिगेज-ड्राईबीस: मुझे पता है कि सी ++ दृष्टिकोण एक अमूर्त वर्ग घोषित करना होगा, लेकिन मैट्रिक्स कंप्यूटेशंस के लिए उपयोग की जाने वाली लाइब्रेरी में जब आप अंतर्निहित प्रकार का उपयोग करते हैं तो महत्वपूर्ण अनुकूलन का उपयोग करता है। मैं बस इस लाभ को खोना नहीं चाहता था –

उत्तर

16

सी ++ मानक पुस्तकालय के कार्यान्वयन को वैश्विक नामस्थान में सी पुस्तकालय कार्यों के साथ-साथ std में घोषित करने की अनुमति है। कुछ इसे एक गलती कहते हैं, क्योंकि (जैसा कि आपने पाया है) नामस्थान प्रदूषण आपके नामों के साथ संघर्ष कर सकता है। हालांकि, यह वही तरीका है, इसलिए हमें इसके साथ रहना चाहिए। आपको बस अपना नाम arithmetic::sin के रूप में अर्हता प्राप्त करनी होगी।

मानक (सी ++ 11 17.6.1.2/4) के शब्दों में:

In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (3.3.6) of the namespace std . It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations (7.3.3).

3

तुम सच में, आप हमेशा cmath चारों ओर एक छोटे से आवरण लिख सकता है, की तर्ज पर करना चाहता था, तो:

//stdmath.cpp 
#include <cmath> 
namespace stdmath 
{ 
    double sin(double x) 
    { 
     return std::sin(x); 
    } 
} 

//stdmath.hpp 
#ifndef STDMATH_HPP 
#define STDMATH_HPP 
namespace stdmath { 
    double sin(double); 
} 
#endif 

//uses_stdmath.cpp 
#include <iostream> 
#include "stdmath.hpp" 

double sin(double x) 
{ 
    return 1.0; 
} 

int main() 
{ 
    std::cout << stdmath::sin(1) << std::endl; 
    std::cout << sin(1) << std::endl; 
} 

मुझे लगता है कि संकलक कितना चालाक है, इस पर निर्भर करता है कि अतिरिक्त फ़ंक्शन कॉल से कुछ ओवरहेड हो सकता है।

+0

यह समस्या को पूरी तरह हल नहीं करता है, 'नेमस्पेस mylib { डबल पाप (डबल एक्स) { वापसी 1.0 पर विचार करें; } } int मुख्य() { \t नेमस्पेस mylib का उपयोग कर; std :: cout << stdmath :: पाप (1) << std :: endl; std :: cout << पाप (1) << std :: endl; } 'आपको अभी भी एक "अस्पष्ट कॉल त्रुटि" मिलती है। – alfC

+0

@alfC नहीं आप नहीं करते हैं। इस उत्तर का पूरा बिंदु 'hpp' शीर्षलेख के बजाय' stdmath' की 'cpp' फ़ाइल में' 'को शामिल करने में है। – Ruslan

1

यह इस समस्या को हल करने के लिए सिर्फ एक विनम्र प्रयास है। (सुझावों का स्वागत है।)

मैं इस समस्या से काफी समय से निपट रहा हूं। एक मामले थे समस्या बहुत स्पष्ट है यह मामला है:

#include<cmath> 
#include<iostream> 

namespace mylib{ 
    std::string exp(double x){return "mylib::exp";} 
} 

int main(){ 
    std::cout << std::exp(1.) << std::endl; // works 
    std::cout << mylib::exp(1.) << std::endl; // works 

    using namespace mylib; 
    std::cout << exp(1.) << std::endl; //doesn't works!, "ambiguous" call 
    return 0; 
} 

इस में मेरी राय एक कष्टप्रद बग या कम से कम एक बहुत दुर्भाग्यपूर्ण स्थिति है।(कम से कम जीसीसी में, और जीएनसी लाइब्रेरी का उपयोग - लिनक्स में।)

हाल ही में मैंने इसे समस्या के लिए एक और शॉट दिया। cmath (जीसीसी का) देखकर ऐसा लगता है कि हेडर केवल सी-फ़ंक्शंस को अधिभारित करने और प्रक्रिया में नेमस्पेस को स्क्रू करने के लिए है।

namespace std{ 
    #include<math.h> 
} 
//instead of #include<cmath> 

यह इस के साथ काम करता है

using namespace mylib; 
std::cout << exp(1.) << std::endl; //now works. 

मैं लगभग यकीन है कि यह वास्तव में #include<cmath> के बराबर नहीं है हूँ, लेकिन अधिकांश कार्यों को काम करने के लिए लग रहे हैं।

सबसे बुरी बात यह है कि आखिर में कुछ निर्भरता लाइब्रेरी #inclulde<cmath> होगी। इसके लिए मुझे अभी तक कोई समाधान नहीं मिला।

नोट: कहने के लिए यह सब

namespace std{ 
    #include<cmath> // compile errors 
} 
+2

'नेमस्पेस std' में किसी भी चीज़ की घोषणा यूबी है। – Ruslan