आम तौर पर, constexpr दुष्प्रभावों से मुक्त होना चाहिए। हालांकि, मैंने अभी पाया है कि फेंकने वाले अपवादों के रचनाकारों में दुष्प्रभावों का उपयोग करना संभव है। उस तकनीक का उपयोग constexpr कार्यों के लिए assert() को अनुकरण करने के लिए किया जा सकता है, क्योंकि यह निम्न प्रोग्राम में प्रदर्शित होता है।क्या यह constexpr द्वारा फेंक दिया अपवादों में साइड इफेक्ट्स का उपयोग करने के लिए कानूनी है?
#include <iostream>
#include <cstdlib>
#include <stdexcept>
struct constexpr_precond_violated : std::logic_error
{
constexpr_precond_violated(const char* msg) :
std::logic_error(msg)
{
std::cerr << msg << '\n';
abort(); // to get a core dump
}
};
#define TO_STRING_IMPL(x) #x
#define TO_STRING(x) TO_STRING_IMPL(x)
#define CONSTEXPR_PRECOND(cond, value) \
((!(cond)) ? throw constexpr_precond_violated(\
"assertion: <" #cond "> failed (file: " \
__FILE__ ", line: " TO_STRING(__LINE__) ")") \
: (value))
constexpr int divide(int x, int y)
{
return CONSTEXPR_PRECOND(y != 0, x/y);
}
int main(int argc, char** argv)
{
// The compiler cannot know argc, so it must be evaluated at runtime.
// If argc is 2, the precondition is violated.
return divide(100, argc - 2);
}
मैंने इसे जी ++ 4.7.2 और क्लैंग ++ 3.1 के साथ परीक्षण किया। जब पूर्व शर्त विफल हो जाती है, तो आपको त्रुटि स्थान और कोर डंप मिलता है।
./constexpr_assert some_arg
assertion: <y != 0> failed (file: constexpr_assert.cpp, line: 26)
Aborted (core dumped)
तो यह वर्तमान कंपाइलर्स के साथ काम करता है, लेकिन क्या यह कानूनी सी ++ 11 है?
ब्याज से, क्या होता है यदि आप संकलन-समय निरंतर '0' को दूसरे विभाजन के रूप में 'divide()' के रूप में आपूर्ति करते हैं? क्या * कंपाइलर * "अपवाद फेंकता है"? :) –
static_assert (विभाजन (1, 0)> = 0, "परीक्षण"); बस वापसी विभाजन (1, 0) संकलित नहीं करेगा; क्लैंग के साथ संकलित करता है और केवल रनटाइम पर विफल रहता है। –
आपको लगातार अभिव्यक्तियों और 'constexpr' फ़ंक्शन के बीच अंतर करने के लिए सावधान रहना चाहिए। "Constexpr' जैसे कुछ दुष्प्रभावों से मुक्त होना चाहिए" अपरिहार्य है। 'Constexpr' के बारे में सोचें क्योंकि एक कीवर्ड से अधिक नहीं है ('स्थिर' दिमाग में आता है)। –