İ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.