İddiaya özel mesajlar eklensin mi?


129

Assert tarafından atılan mesajı eklemenin veya düzenlemenin bir yolu var mı? Gibi bir şey kullanmak istiyorum

assert(a == b, "A must be equal to B");

Ardından derleyici satır , zaman vb. Ekler ...

Mümkün mü?


Sen gibi bir makro tanımlamak bu .
HelloGoodbye

Yanıtlar:


240

Etrafta gördüğüm bir hack &&operatörü kullanmak . İşaretçi boş değilse "true" olduğundan, koşulu değiştirmeden aşağıdakileri yapabilirsiniz:

assert(a == b && "A is not equal to B");

Yana assertgösteriler başarısız olduğunu koşulu, çok senin mesajını verir. Yeterli değilse, istediğinizi görüntüleyecek kendi myAssertişlevinizi veya makronuzu yazabilirsiniz .


27
Diğer bir seçenek, işlenenleri tersine çevirmek ve virgül operatörünü kullanmaktır. Ekstra parantezlere ihtiyacınız var, böylece virgül, bağımsız değişkenler arasında bir sınırlayıcı olarak değerlendirilmez:assert(("A must be equal to B", a == b));
Keith Thompson

3
Yine de değişkenlerin değerlerini şu şekilde yazdırabilmek güzel olurdu:assert(a == b && "A (" << A << ") is not equal to B (" << B << ")");
Frank

7
@Frank, printfherhangi bir şey yazdırırsa sıfır olmayan bir değer döndürür, bu nedenle böyle bir şey yapabilirsiniz assert(a == b && printf("a (%i) is not equal to b (%i)", a, b)), ancak bu noktada muhtemelen kendi iddia sarmalayıcınızı yazmalısınız.
zneak

1
Kötü kod! Bunu anlamıyorum! A == b yanlışsa, ve ifadesi de yanlış olmalıdır ve bu nedenle dize değerlendirilmemelidir.
ragnarius

1
@TUIlover, C string değişmezleri böyle çalışmaz; derleme zamanı sabitleri ve bu bağlamda kullanımları önemsiz bir şekilde optimize edilmiştir. Çalışma zamanı maliyeti yoktur.
zneak

45

Diğer bir seçenek, işlenenleri ters çevirmek ve virgül operatörünü kullanmaktır. Ekstra parantezlere ihtiyacınız var, böylece virgül, bağımsız değişkenler arasında bir sınırlayıcı olarak değerlendirilmez:

assert(("A must be equal to B", a == b));

(bu, daha iyi görünürlük için yukarıdaki yorumlardan kopyalandı)


3
Bu harika bir yaklaşım, küçük bir sorunla, g ++ 'da "-Wunused-value
v010dya

1
veya bir makro ile: #ifndef m_assert #define m_assert (ifade, mesaj) assert ((mesaj, ifade)) #endif
Szymon Marczak

Bir makro sarmalayıcı kullanmak gcc uyarısından kaçınmanızı sağlar:#define m_assert(expr, msg) assert(( (void)(msg), (expr) ))
Jander

25

İletiyi kabul eden ve her şeyi net bir şekilde yazdıran assert makrosu sürümüm:

#include <iostream>

#ifndef NDEBUG
#   define M_Assert(Expr, Msg) \
    __M_Assert(#Expr, Expr, __FILE__, __LINE__, Msg)
#else
#   define M_Assert(Expr, Msg) ;
#endif

void __M_Assert(const char* expr_str, bool expr, const char* file, int line, const char* msg)
{
    if (!expr)
    {
        std::cerr << "Assert failed:\t" << msg << "\n"
            << "Expected:\t" << expr_str << "\n"
            << "Source:\t\t" << file << ", line " << line << "\n";
        abort();
    }
}

Şimdi bunu kullanabilirsin

M_Assert(ptr != nullptr, "MyFunction: requires non-null argument");

Ve başarısızlık durumunda şöyle bir mesaj alacaksınız:

Onaylama başarısız oldu: MyFunction: boş olmayan bağımsız değişken gerektirir

Beklenen: ptr! = Nullptr

Kaynak: C: \ MyProject \ src.cpp, satır 22

Güzel ve temiz, kodunuzda kullanmaktan çekinmeyin =)


Güzel bir. Çok kullanışlı
Killrazor

Biraz kafam karıştı. #Expr, doğrudan ikame için bir dize olarak kabul edilir mi? #Expr ve Expr arasındaki fark nedir?
Minh Tran

@MinhTran Varsayalım ki iddia koşulunuz x == y. Sonra İfade içine genişler if( !(x == y))ve burası koşulun kontrol edildiği yerdir ve # İfade, "x == y"daha sonra hata mesajına koyduğumuz dize değişmezine genişler .
Eugene Magdalits

Ne yazık ki, bu çözüm, ayrılmış tanımlayıcıların kullanılması nedeniyle tanımsız davranışa neden olur.
Monica'yı

19
BOOST_ASSERT_MSG(expre, msg)

http://www.boost.org/doc/libs/1_51_0/libs/utility/assert.html

Bunu doğrudan kullanabilir veya Boost'un kodunu kopyalayabilirsiniz. Ayrıca, Boost assert'in yalnızca başlık olduğunu unutmayın; bu nedenle, tüm Boost'u yüklemek istemiyorsanız, yalnızca o tek dosyayı alabilirsiniz.


@Jichao, assert arayüzünü uygulamakla ne demek istiyorsun?
TARC

7

Zneak'ın cevabı kodu bir şekilde büktüğü için, daha iyi bir yaklaşım, sadece bahsettiğiniz metin metnini yorumlamaktır. yani .:

assert(a == b); // A must be equal to B

İddia hatasının okuyucusu, hata mesajından dosya ve satırı yine de arayacağından, tam açıklamayı burada göreceklerdir.

Çünkü günün sonunda bu:

assert(number_of_frames != 0); // Has frames to update

bundan daha iyi okur:

assert(number_of_frames != 0 && "Has frames to update");

yani kodun insan ayrıştırılması açısından. okunabilirliği. Ayrıca dil kesmek de değil.


1
"İddia hatasının okuyucusu, hata mesajından dosya ve satırı yine de arayacağından," - yalnızca gayretli iseler.
Jason S

Sadece hatayı düzeltmek istiyorlarsa demek istiyorsun ... ne aptalca bir yorum
metamorfoz

1
Hayır. İnsanların sorunu görmesini ne kadar kolaylaştırırsanız, harekete geçme olasılıkları da o kadar artar.
Jason S

omuz silkme Katılmıyorum.
metamorfoz

2

assert bir makro / fonksiyon kombinasyonudur. Eğer kullanarak kendi makro / fonksiyon tanımlayabilir __FILE__, __BASE_FILE__, __LINE__özel bir mesaj alır kendi fonksiyonu ile, vs


-6

Vc için assert.h içine aşağıdaki kodu ekleyin,

#define assert2(_Expression, _Msg) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Msg), _CRT_WIDE(__FILE__), __LINE__), 0) )

11
Derleyicinizin başlıklarını değiştirmek kötü bir fikirdir.
Ross Ridge
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.