stringstream operator selection issues - c++

I have a class constructor like so:
DotDashLogMatcher( std::stringstream const& pattern );
I call it like so:
std::stringstream s;
DotDashLogMatcher( s << "test" );
This is an over-simplified example, but that is essentially what is going on. Here is the exact compiler error I'm getting. Note that for some reason the resulting object that is passed in is a basic_ostream, I am not sure if this is normal. It isn't able to cast it to an std::stringstream like my function expects.
error C2664: 'DotDashLogMatcher::DotDashLogMatcher(const stlpd_std::stringstream &)' : cannot convert parameter 1 from 'stlpd_std::basic_ostream<_CharT,_Traits>' to 'const stlpd_std::stringstream &'
with
[
_CharT=char,
_Traits=stlpd_std::char_traits<char>
]
Reason: cannot convert from 'stlpd_std::basic_ostream<_CharT,_Traits>' to 'const stlpd_std::stringstream'
with
[
_CharT=char,
_Traits=stlpd_std::char_traits<char>
]
No constructor could take the source type, or constructor overload resolution was ambiguous
I'm using VS2003 and STLport on Windows.
Anyone know where I'm going wrong here? Why won't this code compile? I apologize in advance if I am lacking information. I will update my question for those that request more info.

operator<< does not return a std::stringstream because it is inherited from std::ostream. See:
http://www.cplusplus.com/reference/iostream/stringstream/
You may use:
DotDashLogMatcher( s );
Or you may change your method declaration in order to match the return type.

I believe you should split the statement into two separate commands:
s << "test";
DotDashLogMatcher( s );
as the parameter is passed by reference and thus needs to be modifiable, therefore an l-value.

Maybe you want to change:
DotDashLogMatcher( std::stringstream const& pattern );
Into:
DotDashLogMatcher( std::ostream const& pattern );
The problem is that operator << is overloaded for std::ostream and returns a std::ostream.
If you can;t change it there are several workarounds.
std::stringstream s;
s << "test"
DotDashLogMatcher( s );
// slightly more dangerious but should work.
std::stringstream s;
DotDashLogMatcher( static_cast<std::stringstream const&>(s << "test") );

Related

Error with ostream definition

Doing some refactoring, I get an error after moving some code in a class' member function:
std::ostream logStream; // <-- error
std::filebuf fileBuffer;
// Send the output either to cout or to a file
if(sendToCout) {
logStream.rdbuf(std::cout.rdbuf());
}
else {
fileBuffer.open("out.txt", std::ios_base::out | std::ofstream::app);
logStream.rdbuf(&fileBuffer);
}
logStream << "abcd..." << std::endl;
This is the compiler error message:
file.cpp:417: error: calling a protected constructor of class 'std::__1::basic_ostream<char>'
std::ostream logStream;
^
Could this be a solution?
std::filebuf fileBuffer;
std::ostream logStream(&fileBuffer);
...
if(sendToCout) {
logStream.rdbuf(std::cout.rdbuf());
}
If you see e.g. this std::ostream constructor reference you will see that the only public constructor is one taking a pointer to a std::streambuf object, like for example your variable fileBuffer.
So one way to solve your problem is to do
std::filebuf fileBuffer;
std::ostream logStream(&fileBuffer);
A better solution is to use std::ofstream if you want output to a file.
If you want a more generic solution, where it should be possible to use any kind of output stream, then a redesign to use references instead is a possible solution.
Or, you know, try and find an existing logging library which handles everything for you already.

C++ constructor call with boost::filesystem::path as argument - nothing happening

I have a problem that is puzzling me, something is missing from my c++ understanding.
I'm trying to construct an object with a boost::filesystem::path (which itself is constructed from a basic_string) I thought I could save a line of code by doing the construction of the boost path on the same line as I construct my object.
See the example below:
One thing that i don't understand is that, although it doesn't work, I also get no errors. i.e. nothing seems to happen. Why would that be?
class Test {
public:
Test(boost::filesystem::path in) {
std::cout << "Succesful construction" << std::endl;
}
};
int main() {
std::string str("asdf.txt");
boost::filesystem::path p(str);
Test test1(boost::filesystem::path(str)); // Nothing at all happens, but no error
Test test2(p); // "Succesful construction"
}
This is C++'s so-called "most vexing parse." The problem you're running into is that this:
Test test1(boost::filesystem::path(str));
is a declaration for a function named test1 that returns a Test and takes one argument of type boost::filesystem::path named str. The parentheses around str are parsed as superfluous, so the line is interpreted as equivalent to:
Test test1(boost::filesystem::path str);
If you're compiling with C++11, you can replace the outer parentheses with braces:
Test test1{boost::filesystem::path(str)};
Pre-C++11, you can use an extra set of parentheses:
Test test1((boost::filesystem::path(str)));

VC6 - How to create a std::locale with a user defined facet?

I try to create a locale with following line of code:
std::locale loc(std::locale::classic(), new comma);
The definition of comma is:
struct comma : std::numpunct<char> {
char do_decimal_point() const { return ','; }
};
I thought it should work as I saw a similar constructor call in the MSDN documentation to facet. Unfortunatelly I get the error:
error C2664: '__thiscall std::locale::std::locale(const char *,int)' : cannot convert parameter number 1 from 'const class std::locale' in 'const char *'
Do you know, how I can get it right?
There are a some answers on Stackoverflow, which do it right this way (this, or this one). But it seems, that the old VC6 compiler doesn't support this constructor (although the example in the VC6 documentation uses it). But there must be a way to use facets with VC6, otherwise it wouldn't be part of the documentation.
To create a std::locale with a user defined facet we can use _ADDFAC. In the documentation to the locale constructor I found this helpful hint:
[...] you should write _ADDFAC(loc, Facet) to return a new locale that adds the facet Facet to the locale loc, since not all translators currently support the additional template constructors
VC6 doesn't seem to support the additional template constructors.
Sample Code:
std::istringstream iss("333,444"); // comma is decimal mark
std::locale loc(std::_ADDFAC(iss.getloc(), new comma));
iss.imbue(loc);
iss >> e;
std::cout << e << std::endl; // prints 333.444

tellg() for const reference object. "Copying" fstream object

I'm writing a class for working with text files. I would like to "copy" ifstream-object properties. The code below shows how I'm doing it. I have a problem with a function w.m_fin.tellg():
error C2662: 'std::basic_istream<_Elem,_Traits>::tellg' : cannot convert 'this' pointer from 'const std::ifstream' to 'std::basic_istream<_Elem,_Traits> &'
I want to set a file position in the destination object as in the source.
If I make the argument non-const [ Word(Word& w) ] all is OK. But I don't want to make it non-const. What should I do in order to solve this problem?
Thank you
class Word
{
private:
std::ifstream m_fin;
std::string m_in_filename;
public:
Word(const Word& w): m_in_filename( w.m_in_filename )
{
m_fin(m_in_filename);
m_fin.copyfmt( w.m_fin );
m_fin.clear( w.m_fin.rdstate() );
m_fin.seekg( w.m_fin.tellg() );//here I get an error
}
}
Since btellg (by potentially setting fail status) changes the state of the stream (as does seek and any form of read or write operation of course), you can't do that on a const object. However, I expect you could, if you wanted to solve it that way, declare m_fin as mutable, which means the compiler allows it to be changed even for const object.

C++ Passing a wstringstream to another function

I tried to do the following:
wstring wStringStreamToWString(wstringstream uStream)
{
wstring s(uStream.str());
return s;
}
This gives me the compiler error
"C2248 std::basic_ios>_Elem,_Traits>::basic_ios: No access to private members whose declaration was done in std::basic_ios<_Elmen,_Trais>- class."
However, if I do not do this in a separate function, it works fine.
So I guess I am simply doing an mistake when I pass the wstringstream to the function, but I don't see which.
Can anybody help?
Thank you.
Pass the argument by (const as it is not being modified) reference as streams are not copyable:
wstring wStringStreamToWString(wstringstream const& uStream)
{
wstring s(uStream.str());
return s;
}
Though the function, as it stands, seems completely unnecessary.