2010-11-13 28 views
6

Atış yapmayan takas deyimini uygularken, throw() kullanmalı mıyım? Özellikle Atışlı olmayan takas uygularken throw() kullanmalı mıyım?

namespace A 
{ 
    struct B 
    { 
    void swap(B& other) throw() 
    { /* fancy stuff that doesn't throw */ } 
    }; 

    void swap(B& lhs, B& rhs) throw() 
    { lhs.swap(rhs); } 
} 

namespace std 
{ 
    template<> 
    void swap(A::B& lhs, A::B& rhs) throw() 
    { lhs.swap(rhs); } 
} 

I std::swap ait uzmanlık throw() özellikleri koyarak endişe.

Bonus soru:
C++ 0x's noexcept anahtar sözcüğünü kullanırken farklı mıdır?

+0

Bu üç takas bildirimini bire kadar basitleştirebilirsiniz: struct B {friend void swap (B & a, B & b) {/ * ...* /}}; 'sonra basitçe kullanıcıların swap'i kullanarak std :: swap'i kullanmasını; swap (a, b); 'swap'ınızı ADL ile çeker (veya bunu zaten yapan boost :: swap'i kullanabilirler). Özellikle, takasınız için bir tane kullanmaya karar verirseniz, bu durum std :: swap üzerinde bir istisna belirtimine ilişkin endişeyi ortadan kaldırır. –

cevap

4

C++ 03'te onu buraya koyabilirsiniz, ama eğer süslü şeylerin atmadığı doğruysa, temel olarak sadece belgelerdir. Fonksiyona yapılan çağrıların etrafına try/catch(...) { std::unexpected(); } eşdeğerini ekleyerek performansı etkileyebilir veya etkilemeyebilir: performansı etkilemeden yapıp yapamayacağı uygulamaya bağlıdır.

Eğer operatör "doğru" cevap verir, böylece daha sonra aniden olmayan atma istisna özelliklere sahip olmaya değer olur, C++ 0x ile noexcept operatörü (5.3.7) kullanmak üzere planlıyorsanız. noexcept operatörünün ne için olduğunu bilmiyorum, ancak bunun için akıllı bir genel kullanım varsa, örneğin bir şey atmadığında daha verimli hale gelen algoritmalar varsa, sanırım bu işlevler olmayan -almak, faydası ne olursa olsun. Örneğin

:

void foo() noexcept; 
void bar(); 

template <void(*FUNC)()> 
void generic_thing() { 
    if (noexcept(FUNC()) { 
     // this won't throw, perhaps we can somehow take advantage of that 
     FUNC(); 
    } else { 
     // this might throw 
     FUNC(); 
    } 
} 

Eski stil istisna özellikleri (dinamik istisna özellikli) (C++ 03 ve anlamsız) C++ 0x ile kaldırılmıştır.

+0

'noexcept' operatörünün bir ifade gerektirmez. yani noexcept == noexcept (doğru). FCD’de §15.4-1’e bakınız. –

+1

@caspin: 'noexcept' * operatör * yapar. 5.3.7'de tanımlanan tek bir operatördür ve bir ifadenin değerlendirmeden * atıp atamayacağını test eder. Bir istisna belirtiminde * kullanılan noexcept * anahtar kelimesinin * bir ifade gerektirmediğini kabul etti. Oraya neden (doğru) koyduğumdan emin değilim. –

+0

, "noexcept" operatöründe bir "bool constexpr" döndürüyor mu? Kesinlikle mümkün olduğunu söyleyebilirim ve bu yüzden şablon parametresi olarak kullanmak mümkün olmalı ... Tuzuna değen herhangi bir derleyicinin ölü dalı ortadan kaldıracağını ve sonucun hesaplanabilir olması durumunda "eğer" nin tamamen kaldırılacağından şüpheleniyorum. derleme zamanında ... ve neden olmasın? –

1

Realistically, no. İstisna özellikleri hoş bir fikirdi, ancak gerçekleri, kodun çoğunluğuna yardımcı olmaktan çok engellediler. Kimse onları kullanmaz ve C++ 0x'de kullanımdan kaldırılır. Modern C++ 'da istisna şartnamelerini yazarak zaman harcamayın.

+1

İstisna özelliklerinin kötü bir fikir olduğunu ve kullanımdan kaldırıldığının farkındayım. 'Throw() '(boş şartname) kuralın istisnası olduğunu düşündüm. "Noexcept" in, "throw()" ı bir derleme zamanı ifadesi aracılığıyla açma ve kapama yeteneğiyle güncellenmiş bir sürümü olduğunu düşünmüştüm. –

3

Bu iyi bir fikir değil, hayır. Bunun sebebi, standardın, throw() doğruluğunu zorunlu kılmanın imkânsız olduğunu bilmesidir; bu, throw()'un ilk etapta getirilmesidir. Özellikle, örneğe bağlı olarak bir istisnanın atılabileceği ya da atılamayacağı şablonlarda, şablon örneği olmadan doğrulığın kontrol edilmesi imkansızdır. Bu nedenle standart, istisna belirticisini zorlamak için derleyicilere gerek duymaz; Aslında, , bir ifadeyi reddetmekten bir ifadeyi "sadece, çalıştırıldığında çalıştırılan fonksiyonun izin vermediği veya içerdiği işlevin izin vermediği bir istisna atabileceği için" (15.4/11).

throw() dokümantasyondan başka bir etkiye sahip değilse, o zaman yorumlanmalıdır; Bu şekilde en azından insan gözlemciyi yanıltma riski taşımaz.

noexcept ile durum tamamen farklıdır. noexcept farklı bir nedenden dolayı gelir; performansın Eğer size derleyiciyi garanti edemezse, istisna atılmaz, ardından derleyici bazı optimizasyonlar gerçekleştirir. Ama size çekleri kendiniz yapmak zorunda kalacak. Yani, eğer swap(), noexcept'u belirtiyorsa, o zaman atmıyorsa (ve bunun sebebi onun varoluş nedeni) iyi bir fikirdir.

+0

"Bu nedenle standart, derleyicilerin özel koşul belirticisini zorlamasını gerektirmiyor." - bundan daha fazlası, standart, derleyicilerin * istisna özelliklerini (15.4/10) zorlamadığını gerektirir. –

+0

@SteveJessop doğru, beni düzeltdiğin için teşekkürler. Bu arada, 15.4/11. – wilhelmtell

+0

@wilhelm: bir düzeltme, sadece ekstra bilgi :-) demek istemedi. Numaram, ISO/IEC 14882: 2003 (E) 'den, yani C++ 03'ten. Dediğiniz gibi, C++ 0x FCD'de 15.4/11'dir. –

İlgili konular