class C {
using namespace std; // error
};
namespace N {
using namespace std; // ok
}
int main () {
using namespace std; // ok
}
संपादित करें : इसके पीछे प्रेरणा जानना चाहते हैं।
class C {
using namespace std; // error
};
namespace N {
using namespace std; // ok
}
int main () {
using namespace std; // ok
}
संपादित करें : इसके पीछे प्रेरणा जानना चाहते हैं।
class/struct
। यह सिर्फ अनुमति नहीं है। लेकिन स्वीकृत जवाब इसे खारिज करने के लिए बहुत तार्किक तर्क पर चर्चा करता है। यानी कहां विचार करना है Hello::World
और कहां विचार करना है World
। आशा है कि संदेह को साफ करता है।
जवाबों:
मैं ठीक से नहीं जानता, लेकिन मेरा अनुमान है कि कक्षा के दायरे में इसकी अनुमति देने से भ्रम पैदा हो सकता है:
namespace Hello
{
typedef int World;
}
class Blah
{
using namespace Hello;
public:
World DoSomething();
}
//Should this be just World or Hello::World ?
World Blah::DoSomething()
{
//Is the using namespace valid in here?
}
चूंकि ऐसा करने का कोई स्पष्ट तरीका नहीं है, मानक केवल यह कहता है कि आप नहीं कर सकते।
अब, यह कारण कम भ्रमित है जब हम नेमस्पेस स्कैप्स बात कर रहे हैं:
namespace Hello
{
typedef int World;
}
namespace Other
{
using namespace Hello;
World DoSomething();
}
//We are outside of any namespace, so we have to fully qualify everything. Therefore either of these are correct:
//Hello was imported into Other, so everything that was in Hello is also in Other. Therefore this is okay:
Other::World Other::DoSomething()
{
//We're outside of a namespace; obviously the using namespace doesn't apply here.
//EDIT: Apparently I was wrong about that... see comments.
}
//The original type was Hello::World, so this is okay too.
Hello::World Other::DoSomething()
{
//Ditto
}
namespace Other
{
//namespace Hello has been imported into Other, and we are inside Other, so therefore we never need to qualify anything from Hello.
//Therefore this is unambiguiously right
World DoSomething()
{
//We're inside the namespace, obviously the using namespace does apply here.
}
}
using namespace Hello;
दूसरे के लिए namespace
भी लागू होती है (और extern
इसके अंदर फ़ंक्शन की घोषणा करते हुए )।
Hello::World Blah::DoSomething()
या Blah::World Blah::DoSomething()
(यदि इसे अनुमति दी गई थी), तो सदस्य प्रकार की परिभाषा का वापसी प्रकार भाषा में वर्ग के दायरे में नहीं माना जाता है, इसलिए इसे योग्य होना चाहिए। जगह की वैध उदाहरण पर विचार करें using
एक साथ typedef Hello::World World;
वर्ग दायरे में। इसलिए वहां कोई आश्चर्य नहीं होना चाहिए।
क्योंकि C ++ मानक स्पष्ट रूप से इसे मना करता है। C ++ 03 C7.3.4 से [namespace.udir]:
उपयोग-निर्देश : नेमस्पेस का उपयोग :: ऑप्ट नेस्टेड-नेम-स्पेसियर ऑप्ट नेमस्पेस-नाम ;
एक प्रयोग-निर्देश वर्ग के दायरे में प्रकट नहीं होगा, लेकिन नाम स्थान के दायरे या ब्लॉक दायरे में दिखाई दे सकता है। [नोट: एक प्रयोग-निर्देश में एक नाम-स्थान की तलाश करते समय, केवल नामस्थान नामों पर विचार किया जाता है, 3.4.6 देखें। ]
C ++ मानक इसे क्यों मना करता है? मुझे नहीं पता, आईएसओ समिति के एक सदस्य से पूछें जिसने भाषा मानक को मंजूरी दी थी।
मेरा मानना है कि तर्क यह है कि यह संभवतः भ्रामक होगा। वर्तमान में, क्लास स्तर के पहचानकर्ता को संसाधित करते समय, लुकअप पहले वर्ग के दायरे में और फिर एनक्लोजिंग नेमस्पेस में खोज करेगा। using namespace
क्लास स्तर पर अनुमति देने से लुकअप कैसे किया जाता है, इस पर कुछ दुष्प्रभाव होंगे। विशेष रूप से, इसे उस विशेष वर्ग के दायरे की जाँच करने और संलग्न नामस्थान की जाँच करने के बीच कभी-कभी करना होगा। वह है: 1) वर्ग स्तर और प्रयुक्त नाम स्थान स्तर लुकअप का विलय, 2) वर्ग के दायरे के बाद उपयोग किए गए नाम स्थान की खोज करना लेकिन किसी भी अन्य वर्ग गुंजाइश से पहले, 3) संलग्न नामस्थान से ठीक पहले इस्तेमाल किए गए नामस्थान को देखें। 4) लुकअप एन्क्लेपिंग नामस्थान के साथ विलय हो गया।
।
namespace A {
void foo() {}
struct B {
struct foo {};
void f() {
foo(); // value initialize a A::B::foo object (current behavior)
}
};
}
struct C {
using namespace A;
struct foo {};
void f() {
foo(); // call A::foo
}
};
।
namespace A {
void foo() {}
}
void bar() {}
struct base {
void foo();
void bar();
};
struct test : base {
using namespace A;
void f() {
foo(); // A::foo()
bar(); // base::bar()
}
};
।
namespace A {
void foo( int ) { std::cout << "int"; }
}
void foo( double ) { std::cout << "double"; }
struct test {
using namespace A;
void f() {
foo( 5.0 ); // would print "int" if A is checked *before* the
// enclosing namespace
}
};
using
नेमस्पेस स्तर पर घोषणा को लागू करने का होता है। यह उस पर कोई नया मूल्य नहीं जोड़ेगा, लेकिन दूसरी ओर संकलक कार्यान्वयनकर्ताओं के लिए जटिल खोज होगी। Namespace आइडेंटिफायर लुकअप अब स्वतंत्र है जहां से कोड में लुकअप ट्रिगर है। जब किसी वर्ग के अंदर, यदि लुकअप को पहचानकर्ता को क्लास स्कोप पर नहीं मिलता है तो वह वापस नेमस्पेस लुकअप में आ जाएगा, लेकिन यह वही नेमस्पेस लुकअप है जिसका उपयोग फंक्शन डेफिनिशन में किया जाता है, नए स्टेट को बनाए रखने की कोई आवश्यकता नहीं है। जब using
घोषणा नाम स्थान स्तर पर पाया जाता है, की सामग्री का इस्तेमाल किया नाम स्थान रहे लाया के लिए कि नेम स्पेस में सभी नाम स्थान को शामिल लुकअप। अगरusing namespace
वर्ग के स्तर पर अनुमति दी गई थी, जहाँ पर लुकअप ट्रिगर किया गया था, उसके आधार पर सटीक समान नामस्थान के नामस्थान लुकअप के लिए अलग-अलग परिणाम होंगे, और यह बिना किसी अतिरिक्त मान के लुकअप के कार्यान्वयन को और अधिक जटिल बना देगा।वैसे भी, मेरी सिफारिश घोषणा को नियोजित करने के लिए नहीं है using namespace
। यह सभी नाम स्थान की सामग्री को ध्यान में रखे बिना कोड को सरल बनाता है।
using
मौजूद हैं। जानबूझकर गहरी नेस्टेड लंबे नामस्थानों में चीजों की घोषणा करके। glm
जब ग्राहक उपयोग करता है तो सुविधाओं को सक्रिय / प्रस्तुत करने के लिए एग करता है और कई तरकीबों का उपयोग करता है using
।
using namespace std::placeholders
। cf en.cppreference.com/w/cpp/utility/functional/bind
namespace ph = std::placeholders;
यह शायद खुलेपन बनाम बंद होने के कारण अस्वीकृत है ।
कक्षाओं में नामस्थान आयात करने से इस तरह के मजेदार मामले सामने आएंगे:
namespace Foo {}
struct Bar { using namespace Foo; };
namespace Foo {
using Baz = int; // I've just extended `Bar` with a type alias!
void baz(); // I've just extended `Bar` with what looks like a static function!
// etc.
}
मुझे लगता है कि यह भाषा का दोष है। आप नीचे दिए गए समाधान का उपयोग कर सकते हैं। इस वर्कअराउंड को ध्यान में रखते हुए, केस के लिए नाम संघर्षों के रिज़ॉल्यूशन के नियमों का सुझाव देना आसान है, जब भाषा बदली जाएगी।
namespace Hello
{
typedef int World;
}
// surround the class (where we want to use namespace Hello)
// by auxiliary namespace (but don't use anonymous namespaces in h-files)
namespace Blah_namesp {
using namespace Hello;
class Blah
{
public:
World DoSomething1();
World DoSomething2();
World DoSomething3();
};
World Blah::DoSomething1()
{
}
} // namespace Blah_namesp
// "extract" class from auxiliary namespace
using Blah_namesp::Blah;
Hello::World Blah::DoSomething2()
{
}
auto Blah::DoSomething3() -> World
{
}
using namespace
। C # कुछ समान अनुमति देता है, लेकिन केवल फ़ाइल स्कोप पर। C ++ काusing namespace
आपको एक नाम स्थान दूसरे में शामिल करने की अनुमति देता है।