![](/img/trans.png)
[英]Redirect from a std::ostringstream to another std::ostringstream
[英]Need a macro to create a std::string from a std::ostringstream and a << arg list
我想編寫一個宏,該宏將std :: ostream&operator <<串聯對象的列表作為唯一參數,並將合並后的字符串作為單個std :: string對象傳遞給函數。 將合並的字符串傳遞給函數的能力是關鍵。 在下面的示例中,我知道只需將宏定義為ERR_MSG(inputs) std::cout << "ERROR: " << inputs
,即可將示例本身重寫為工作,但是將輸出發送至std :: cout是不是目標,這只是我為示例選擇的測試目標。
我正在使用GCC 4.1.2(Red Hat 4.1.2-52),並且無法升級它。 這是我嘗試過的非常精簡的版本:
#include <sstream>
#include <iostream>
#define ERR_MSG(inputs) errMsg(std::ostringstream().str()) // 1
#define ERR_MSG(inputs) errMsg((std::ostringstream()<<inputs).str()) // 2
<aReturnType> errMsg(const std::string& msg) // use with 1 & 2
{
std::cout << "\nERROR: " << msg << "\n\n";
return <someObjectCreatedBasedOnTheInput>;
}
#define ERR_MSG(inputs) errMsg(std::ostringstream()<<inputs) // 3
<aReturnType> errMsg(const std::ostringstream& msg) // use with 3
{
std::cout << "\nERROR: " << msg.str() << "\n\n";
return <someObjectCreatedBasedOnTheInput>;
}
int main()
{
ERR_MSG("A number: " << 24 << ", a char: " << 'c' << ", that's all!");
}
宏#1可以編譯,但是當然只打印“”以外的消息。 宏2和3都不編譯,但出現以下錯誤:
#define ERR_MSG(inputs) errMsg((std::ostringstream()<<inputs).str()) // 2
error: ‘struct std::basic_ostream<char, std::char_traits<char> >’ has no member named ‘str’
#define ERR_MSG(inputs) errMsg(std::ostringstream()<<inputs) // 3
no matching function for call to ‘errMsg(std::basic_ostream<char, std::char_traits<char> >&)’
note: candidates are: char* errMsg(const std::string&)
note: char* errMsg(const std::ostringstream&)
我對沒有宏如何重寫它不感興趣; 我自己可以很容易地做到這一點。
===更新:===我忘了提到在實際使用情況下,由宏調用的函數返回的對象可能由宏的調用者使用。 這會使所有無法在單個表達式中實現的宏實現無效,其結果是該宏調用的函數的返回類型。 宏的“不執行任何操作”實現(對於發行版本)將簡單地將空的std :: string傳遞給函數,而不管“輸入”是什么。 對不起,您之前沒有提到。
您當前的問題是,所有各種operator<<
函數都返回一個ostream&
,而不是ostringstream&
。 您可以使用簡單的演員表解決此問題:
#define ERR_MSG(inputs) errMsg((static_cast<std::ostringstream&>(std::ostringstream().flush() << inputs)).str())
需要flush
是因為std::ostringstream()
是臨時的。 因此,您不能在其上調用帶有左值引用的函數(即: std::ostream&
)。 像大多數operator<<
變體一樣的函數。 flush
調用所做的只是將this
指針作為左值引用返回。
如果您願意使用某些GCC擴展名 ,您可以在一個宏塊中聲明一個實際的ostringstream,以便可以使用.str()方法而無需進行強制轉換:
#define ERR_MSG(inputs) \
do { std::ostringstream _s_; _s_<<inputs;errMsg(_s_.str()); } while(false)
演示: http : //ideone.com/clone/y56lc
使用do { } while (false)
慣用語do { } while (false)
使宏成為幾行。
#define ERR_MSG(inputs) \
do { \
std::ostringstream osERR_MSG; \
osERR_MSG << inputs; \
errMsg(osERR_MSG.str()); \
} while (false)
int main() {
if (1) ERR_MSG("A number: " << 24 << ", a char: " << 'c' << ", that's all!");
else return 0;
}
我之所以使用這樣奇怪的名稱osERR_MSG
是為了盡可能避免這種情況:
int osERR_MSG = 7;
ERR_MSG(osERR_MSG);
#include <sstream>
#include <iostream>
#define ERR_MSG(inputs) errMsg(std::ostringstream().flush()<<inputs)
int errMsg(std::ostream& os)
{
std::ostringstream& oss(static_cast<std::ostringstream&>(os));
const std::string& str(oss.str());
std::cout << "\nERROR: " << str << "\n\n";
return str.length();
}
int main()
{
int i = ERR_MSG("A number: " << 24 << ", a char: " << 'c' << ", that's all!");
std::cout << i << "\n";
}
我不會創建std::ostringstream
,而是有一個從std::ostream
派生的類的析構函數調用的函數。 這是此方法的示例:
#include <sstream>
#include <iostream>
void someFunction(std::string const& value)
{
std::cout << "someFunction(" << value << ")\n";
}
void method(std::string const& value)
{
std::cout << "method(" << value << ")\n";
}
class FunctionStream
: private virtual std::stringbuf
, public std::ostream
{
public:
FunctionStream()
: std::ostream(this)
, d_function(&method)
{
}
FunctionStream(void (*function)(std::string const&))
: std::ostream(this)
, d_function(function)
{
}
~FunctionStream()
{
this->d_function(this->str());
}
private:
void (*d_function)(std::string const&);
};
int main(int ac, char* av[])
{
FunctionStream() << "Hello, world: " << ac;
FunctionStream(&someFunction) << "Goodbye, world: " << ac;
}
該示例用法未使用宏,但是可以將其輕松包裝在上面的FunctionStream()
周圍。 注意,在宏中,您可能需要確保宏用戶看到的類型為std::ostream&
類型std::ostream&
而不是臨時類型,以便可以直接與用戶定義的輸出運算符一起使用。 為此,您應該插入std::ostream
直接支持的一種類型,它沒有任何作用,但返回std::ostream&
,例如:
#define SomeMacro(output) FunctionStream(&someFunction) << "" << output
恢復Nicol的答案是迄今為止最好的答案:
您當前的問題是,所有各種operator<<
函數都返回一個ostream&
,而不是ostringstream&
。 您可以使用簡單的演員表解決此問題:
#define ERR_MSG(inputs) errMsg((static_cast<std::ostringstream&>(std::ostringstream().flush() << inputs)).str())
當然,這仍然有一個問題(就像這里的所有答案一樣)
ERR_MSG(x ? "x is true" : "x is false")
會以一種奇怪而混亂的方式行事。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.