यह एक बड़ी परियोजना के अंदर हो रहा है इसलिए मैं वास्तव में न्यूनतम पुनरुत्पादित उदाहरण पोस्ट नहीं कर सकता लेकिन मैं वैसे भी पूछने की कोशिश करूंगा। मैं एक ढांचे के साथ एकीकृत बेंचमार्क एप्लिकेशन की एक सूची बना रहा हूं जिस पर हम काम कर रहे हैं और उनमें से एक पर हमें to_string के साथ (फ्लोट -> स्ट्रिंग) बनाने की आवश्यकता है, जो अल्पविराम से अलग परिणाम को पुन: उत्पन्न करता है।

| Monitored values:
| [ my_time_monitor.average = 61720,000000 ]

यह जिम्मेदार कार्य है:

std::string operating_point_parser::operator()(const int32_t num_threads, const float exec_time_ms) const {
    return "{\"compute\":[{\"knobs\":{\"num_threads\":" + std::to_string(num_threads) + "},\"metrics\":{\"exec_time_ms\":[" + std::to_string(exec_time_ms) + ",0]}}]}";
}

चूंकि मैंने कहा कि वही सटीक कार्य अन्य अनुप्रयोगों द्वारा बुलाया जा रहा है जो इस अप्रत्याशित व्यवहार को नहीं दिखाते हैं, मेरा अनुमान है कि कुछ आंतरिक संकलन झंडे गड़बड़ कर रहे हैं।

set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -DENABLE_THREADS  -DHAVE_RANDOM -DHAVE_UNISTD_H  -DHAVE_SYS_FILE_H -DHAVE_SYS_MMAN_H -DHAVE_CONFIG_H -DVIPSDATASET_PATH=\"\\\"${CMAKE_CURRENT_SOURCE_DIR}/dataset/orion_18000x18000.v\\\"\"" )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHAVE_RANDOM -DHAVE_UNISTD_H -DIM_PREFIX=\"\\\"${CMAKE_CURRENT_SOURCE_DIR}/dataset\\\"\" -DIM_EXEEXT=\"\\\"\\\"\" -DIM_LIBDIR=\"\\\"${CMAKE_INSTALL_PREFIX}/lib\\\"\" -DGETTEXT_PACKAGE=\"\\\"vips7\"\\\" -DHAVE_SYS_FILE_H -DHAVE_SYS_MMAN_H -DHAVE_CONFIG_H")

यदि आप संपूर्ण एप्लिकेशन कोड पर एक नज़र डालना चाहते हैं तो यहां लिंक है। operating_point_parse::operator() को margot::compute::push_custom_monitor_values() के अंदर कहा जाता है।

0
Barnercart 8 फरवरी 2021, 13:45

2 जवाब

सबसे बढ़िया उत्तर

जैसा कि https://en.cppreference.com/w/ के नोट्स में बताया गया है cpp/string/basic_string/to_string, to_string स्वरूपण उद्देश्यों के लिए वर्तमान स्थान पर निर्भर करता है:

std::to_string स्वरूपण उद्देश्यों के लिए वर्तमान लोकेल पर निर्भर करता है, और इसलिए कई थ्रेड्स से std::to_string पर समवर्ती कॉल के परिणामस्वरूप कॉल का आंशिक क्रमांकन हो सकता है। C++17 एक उच्च-प्रदर्शन लोकेल-स्वतंत्र विकल्प के रूप में std::to_chars प्रदान करता है।

इसलिए, यदि आप कॉमन्स के बजाय डॉट्स रखना चाहते हैं, तो आपको वर्तमान लोकेल को एडजस्ट करना होगा।

या वैश्विक लोकेल को std::locale::global(...) के साथ बदलने के बजाय आप stringstream और imbue() केवल उस स्ट्रीम पर लोकेल का उपयोग कर सकते हैं, उदाहरण के लिए।

stringstream ss;
ss.imbue( locale you want )
ss << ... write what you need
ss.str(); // get formatted string
5
StPiere 8 फरवरी 2021, 13:59

std::to_string स्वरूपण के लिए वर्तमान में सक्रिय स्थान का उपयोग करता है।

आप सी लोकेल नाम का उपयोग करके सक्रिय लोकेल सेट कर सकते हैं:

const char* locale = "C";
std::locale::global(std::locale(locale));

स्थानीय नाम का अर्थ C मानक (C11 ड्राफ्ट से उद्धरण) में निर्दिष्ट है:

7.11.1.1 सेटलोकेल फ़ंक्शन

लोकेल के लिए "सी" का मान सी अनुवाद के लिए न्यूनतम वातावरण निर्दिष्ट करता है; लोकेल के लिए "" का मान स्थानीय-विशिष्ट मूल परिवेश को निर्दिष्ट करता है। अन्य कार्यान्वयन-परिभाषित स्ट्रिंग्स को सेटलोकेल के दूसरे तर्क के रूप में पारित किया जा सकता है।


वह मान JSON स्ट्रिंग के अंदर स्वरूपित होने जा रहा है

इस मामले में, और आम तौर पर जब भी आप ऐसी शैली का उपयोग करके प्रारूपित करना चाहते हैं जो वैश्विक लोकेल पर निर्भर नहीं होनी चाहिए, तो std::to_string से बचना चाहिए।

चूंकि आपने इससे बचने की सलाह दी थी, इसलिए आप क्या सलाह देंगे?

कुछ भी जो लोकेल का उपयोग नहीं करता है, या आपको वैश्विक लोकेल का उपयोग करने के बजाय उपयोग करने के लिए लोकेल निर्दिष्ट करने देता है। उदाहरण के लिए:

std::format("{}", 0.42);                   // doesn't use locale
std::format(std::locale("C"), "{}", 0.42); // use specific locale

एक अन्य उदाहरण इम्ब्यूड लोकेल के साथ एक स्ट्रिंगस्ट्रीम है जैसा कि दूसरे उत्तर में सुझाया गया है।

2
eerorika 8 फरवरी 2021, 14:28