Outputting user defined structure with boost::log - c++

I'm trying to output content of boost::asio::streambuf object with boost::log library. I defined operator<< overload in the following way:
ostream& operator<<(ostream& ostr, const boost::asio::streambuf& buffer)
{
for (size_t i = 0; i < buffer.size(); ++i)
{
ostr << hex << (int) buffer_cast<const char*>(buffer.data())[i] << " ";
}
return ostr;
}
But after trying to output the content of the buffer:
BOOST_LOG_TRIVIAL(trace) << buffer;
I have the following error:
In file included from
/home/bobeff/work/asio_netcomm_poc/third_party/lib/boost/boost/log/sources/record_ostream.hpp:31:0,
from /home/bobeff/work/asio_netcomm_poc/third_party/lib/boost/boost/log/trivial.hpp:23,
from /home/bobeff/work/asio_netcomm_poc/server/src/server.cpp:14:
/home/bobeff/work/asio_netcomm_poc/third_party/lib/boost/boost/log/utility/formatting_ostream.hpp:
In instantiation of 'typename
boost::log::v2_mt_posix::aux::enable_if_formatting_ostream::type boost::log::v2_mt_posix::operator<<(StreamT&, T&)
[with StreamT =
boost::log::v2_mt_posix::basic_formatting_ostream; T =
boost::asio::basic_streambuf<>; typename
boost::log::v2_mt_posix::aux::enable_if_formatting_ostream::type =
boost::log::v2_mt_posix::basic_formatting_ostream&]':
/home/bobeff/work/asio_netcomm_poc/third_party/lib/boost/boost/log/sources/record_ostream.hpp:212:51:
required from 'typename
boost::log::v2_mt_posix::aux::enable_if_record_ostream::type boost::log::v2_mt_posix::operator<<(StreamT&, T&)
[with StreamT = boost::log::v2_mt_posix::basic_record_ostream; T
= boost::asio::basic_streambuf<>; typename boost::log::v2_mt_posix::aux::enable_if_record_ostream::type =
boost::log::v2_mt_posix::basic_record_ostream&]'
/home/bobeff/work/asio_netcomm_poc/server/src/server.cpp:88:47:
required from here
/home/bobeff/work/asio_netcomm_poc/third_party/lib/boost/boost/log/utility/formatting_ostream.hpp:840:19:
error: cannot bind
'boost::log::v2_mt_posix::basic_formatting_ostream::ostream_type
{aka std::basic_ostream}' lvalue to 'std::basic_ostream&&'
strm.stream() << value;
^ In file included from /usr/include/c++/4.8/iostream:39:0,
from /home/bobeff/work/asio_netcomm_poc/server/src/server.cpp:1:
/usr/include/c++/4.8/ostream:602:5: error: initializing argument 1
of 'std::basic_ostream<_CharT, _Traits>&
std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&)
[with _CharT = char; _Traits = std::char_traits; _Tp =
boost::asio::basic_streambuf<>]'
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
What is the right way to output the content of the buffer?

Your operator<< is not found by ADL. See the first part of this answer.

Related

Using a template function in an anonymous namespace

I am trying to use Strong Types and to add stream operator for them.
In my source file I put all of these helpers in an anonymous namespace. One of these helpers is using a template stream operator (utils::to_hex(T)) defined in another header.
namespace { // Anonymous namespace
// Example custom strong type
using custom_type = utils::StrongType<std::uint32_t, struct Custom>;
// Stream operator for custom type
std::ostream &operator<<(std::ostream &_os, const custom_type &_value)
{
return (_os << utils::to_hex(static_cast<std::uint32_t>(_value)));
}
}
int main(void)
{
custom_type c = 0xDEADBEEF;
std::cout << c << std::endl;
}
The whole code: http://cpp.sh/2ln7q
I cannot compile this code. I am stuck with:
test.cc: In function ‘std::ostream& {anonymous}::operator<<(std::ostream&, const custom_type&)’:
test.cc:72:14: error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘utils::ToHex<unsigned int>’)
return (_os << utils::to_hex(static_cast<std::uint32_t>(_value)));
Using the cpp.sh compiler I got:
In function 'std::ostream& {anonymous}::operator<<(std::ostream&, const custom_type&)':
73:65: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
In file included from /usr/include/c++/4.9/istream:39:0,
from /usr/include/c++/4.9/sstream:38,
from /usr/include/c++/4.9/iomanip:45,
from 3:
/usr/include/c++/4.9/ostream:602:5: note: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = utils::ToHex<unsigned int>]'
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
When I remove the anonymous namespace of if I use the static keyword everything is fine.

GCC problem with static_cast<std::u16string>

Summary
I have a class to which I've added a typecast operator to convert to std::u16string. The signature of this operator looks as follows:
operator const std::u16string() const;
In my .cpp file, I try converting an object of my class's type to std::u16string as follows:
std::u16string sUTF16Password = static_cast<std::u16string>(Password_);
On Visual Studio 2017, this works just fine. However, GCC 6.3 on my Raspberry Pi gives the following error at compile time:
error : call of overloaded 'basic_string(MyClass&)' is ambiguous
What is the right way to write this typecast? Searching on Google brings a lot of hits for character encoding conversions, but that's not my problem here. I don't understand why the basic_string constructor is being called here despite using static_cast.
Full example
Here's a minimal example. Compiling it with g++ main.cpp fails on my Raspberry Pi.
#include <iostream>
#include <string>
class MyClass
{
private:
std::u16string Str;
public:
MyClass() { Str = u"abcd"; }
operator const char16_t*() const { return Str.c_str(); }
operator std::u16string() const { return Str; }
};
int main()
{
MyClass Tester;
std::u16string TestStr = static_cast<std::u16string>(Tester);
for (size_t idx = 0; idx < TestStr.size(); idx++)
std::cout << idx << ": " << TestStr[idx] << std::endl;
return 0;
}
The output of gcc --version is gcc (Raspbian 6.3.0-18+rpi1+deb9u1) 6.3.0 20170516.
The full output from g++ main.cpp is:
main.cpp: In function ‘int main()’:
main.cpp:17:61: error: call of overloaded ‘basic_string(MyClass&)’ is ambiguous
std::u16string TestStr = static_cast<std::u16string>(Tester);
^
In file included from /usr/include/c++/6/string:52:0,
from /usr/include/c++/6/bits/locale_classes.h:40,
from /usr/include/c++/6/bits/ios_base.h:41,
from /usr/include/c++/6/ios:42,
from /usr/include/c++/6/ostream:38,
from /usr/include/c++/6/iostream:39,
from main.cpp:1:
/usr/include/c++/6/bits/basic_string.h:476:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_
CharT, _Traits, _Alloc>&&) [with _CharT = char16_t; _Traits = std::char_traits<char16_t>; _Alloc = std::allocator<char16_t>]
basic_string(basic_string&& __str) noexcept
^~~~~~~~~~~~
/usr/include/c++/6/bits/basic_string.h:454:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&
) [with _CharT = char16_t; _Traits = std::char_traits<char16_t>; _Alloc = std::allocator<char16_t>]
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
^~~~~~~~~~~~
/usr/include/c++/6/bits/basic_string.h:397:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_st
ring<_CharT, _Traits, _Alloc>&) [with _CharT = char16_t; _Traits = std::char_traits<char16_t>; _Alloc = std::allocator<char16_t>]
basic_string(const basic_string& __str)
^~~~~~~~~~~~
If I remove the typecast to const char16_t* this example compiles just fine. I still don't understand why having both typecasts is a problem.
If you compile as C++14 (or earlier), you'll get this ambiguous call, because std::u16string(char16_t*) participates in the overload resolution (via MyClass::operator const char16_t*()) as well as MyClass::operator std::u16string() that would appear to be a better match.
This can be overcome in several ways:
Compile as C++17 (or later) with GCC 7 or later (sadly, this doesn't help with GCC 6).
Remove operator const char16_t*().
Add explicit to operator const char16_t*() (or to both conversion operators).

C++ Trying to display data of different types using a template output function

I have made a function that is supposed to output data types which include ints, chars, strings and a class called item. This is the function:
template < typename T >
void Output(const T* first, const T* last, char outforchar= '\0')
{
if (outforchar== '\0')
{
std::for_each(first, last, [](T i){std::cout << i;});
}
else
{
std::for_each(first, last, [outforchar](T i){std::cout << i << outforchar;});
}
}
While this function works for types like ints, chars, and strings. It doesn't work for the item class which has a >> operator which formats the input according to the specifications. The compiler throws this error:
./tempsorter.h:14:47: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
std::for_each(beg, end, [](T i){std::cout << i;});
^
In file included from /usr/include/c++/4.8.2/iostream:39:0,
from psort.cpp:16:
/usr/include/c++/4.8.2/ostream:602:5: error: initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = Product]’
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
In file included from /usr/include/c++/4.8.2/algorithm:62:0,
from ./tempsorter.h:2,
from psort.cpp:18:
/usr/include/c++/4.8.2/bits/stl_algo.h:4411:5: error: ‘_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = const Item*; _Funct = Output(const T*, const T*, char) [with T = Item]::__lambda0]’, declared using local type ‘Output(const T*, const T*, char) [with T = Item]::__lambda0’, is used but never defined [-fpermissive]
for_each(_InputIterator __first, _InputIterator __last, _Function __f)
^
/usr/include/c++/4.8.2/bits/stl_algo.h:4411:5: error: ‘_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = const Item*; _Funct = Output(const T*, const T*, char) [with T = Item]::__lambda1]’, declared using local type ‘Output(const T*, const T*, char) [with T = Item]::__lambda1’, is used but never defined [-fpermissive]
I understand this error and can get rid of it using something like:
for (auto i = first; i != last; ++i)
{
std::cout << i;
}
But then this gives me incorrect outputs so I can't use it at all.
I am expected to traverse through the various types with something like the following:
for (typename E::ConsItr i = e.Begin(); i != e.End(); ++i)
I can't seem to understand how to implement this into the function, what am I doing wrong?
First,
[](T const& i){std::cout << i;}
is probably better. In addition, you probably wrote your << operator wrong.
std::ostream& operator<<(std::ostream& os, const SomeType& x)
it should look like that, and possibly be a friend of your type. Ensure it is in the same namespace as your type. Or you overloades >> instead of <<

Is using a reference parameter with default value good practice?

I have the following code:
#include <string>
#include <iostream>
void f(const std::string& s = "")
{
std::cout << "\"" << s << "\"" << std::endl;
}
int main()
{
std::string s1 = "qwe";
f();
f("asd");
f(s1);
}
How bad (if at all) are the calls with the temporary and without the parameters?
As far as I know this compiles only due to the fact that const reference prolongs the life of the temporary until the end of a method http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
Trying to compile the same example without the const next to s parameter fails.
#include <string>
#include <iostream>
void f(std::string& s = "")
{
std::cout << "\"" << s << "\"" << std::endl;
}
int main()
{
std::string s1 = "qwe";
f();
f("asd");
f(s1);
}
Compilation
g++-5 -O3 -Wall --std=c++11 main.cpp && ./a.out
main.cpp:4:27: error: invalid initialization of non-const reference of type ‘std::string& {aka std::basic_string<char>&}’ from an rvalue of type ‘std::string {aka std::basic_string<char>}’
void f(std::string& s = "")
^
In file included from /usr/include/c++/5/string:52:0,
from main.cpp:1:
/usr/include/c++/5/bits/basic_string.h:2893:7: note: after user-defined conversion: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
^
main.cpp: In function ‘int main()’:
main.cpp:12:5: error: invalid initialization of non-const reference of type ‘std::string& {aka std::basic_string<char>&}’ from an rvalue of type ‘std::string {aka std::basic_string<char>}’
f();
^
In file included from /usr/include/c++/5/string:52:0,
from main.cpp:1:
/usr/include/c++/5/bits/basic_string.h:2893:7: note: after user-defined conversion: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
^
main.cpp:4:6: note: in passing argument 1 of ‘void f(std::string&)’
void f(std::string& s = "")
^
main.cpp:13:10: error: invalid initialization of non-const reference of type ‘std::string& {aka std::basic_string<char>&}’ from an rvalue of type ‘std::string {aka std::basic_string<char>}’
f("asd");
^
In file included from /usr/include/c++/5/string:52:0,
from main.cpp:1:
/usr/include/c++/5/bits/basic_string.h:2893:7: note: after user-defined conversion: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
^
main.cpp:4:6: note: initializing argument 1 of ‘void f(std::string&)’
void f(std::string& s = "")
It's not a horrible practice, but it's generally better to provide overloads:
void f(std::string const& s) { std::cout << "\\" << s << "\\\n"; }
void f() { f(""); }
It avoids some language features that end up being confusing to many people. For example, what does this print?
struct base { virtual void f(int i = 42) { std::cout << i; } };
struct derived : base { void f(int i = 19) { std::cout << i; }};
int main() { base * b = new derived(); b->f(); }
There are also ambiguity errors that can come up when you're using default parameters that don't when you use overloads.
As far as const references in particular, that doesn't really matter much. The default value binds to reference for the lifetime of the function call. It has no effect at all really. You might get better results using values sometimes when the compiler can perform certain optimizations that are not possible with reference parameters, but generally it's not something to be concerned with.
Of course, this doesn't work with non-const references because they don't bind to temporaries.
The default value is for allowing you to call function without any arguments, so use reference parameter with default value if you sometimes will not pass argument to function, otherwise there is no matter to do so.

Mex files on Mountain Lion: explicit instantiation error

I'm working with MATLAB r2012b on Mountain Lion, and XCode version installed is 4.6.1. I've also used the patch at http://www.mathworks.it/support/solutions/en/data/1-IXBVKD/ and then I have typed "mex - setup" and selected the only option available
1: /Applications/MATLAB_R2012b.app/bin/mexopts.sh : Template Options file for building gcc MEX-files
I'm trying to use a framework for sparse modeling (written in C++) which uses mex files. In order to install the previous framework I have to call a matlab file inside the framework which calls mex function: however when I call this function I get the following message...
compilation of: -I./linalg/ -I./decomp/ -I./dictLearn/ dictLearn/mex/mexTrainDL.cpp
./linalg/linalg.h: In member function 'void Matrix<T>::print(const std::string&) const [with T = float]':
./linalg/linalg.h:1084: instantiated from 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]'
./linalg/linalg.h:1084: instantiated from 'void Matrix<T>::print(const std::string&) const [with T = float]'
dictLearn/mex/mexTrainDL.cpp:197: instantiated from here
./linalg/linalg.h:1084: error: explicit instantiation of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]' but no definition available
./linalg/linalg.h: At global scope:
./linalg/linalg.h: In instantiation of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]':
./linalg/linalg.h:1084: instantiated from 'void Matrix<T>::print(const std::string&) const [with T = float]'
dictLearn/mex/mexTrainDL.cpp:197: instantiated from here
./linalg/linalg.h:1084: error: explicit instantiation of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]' but no definition available
./linalg/linalg.h: In instantiation of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]':
./linalg/linalg.h:1084: instantiated from 'void Matrix<T>::print(const std::string&) const [with T = float]'
dictLearn/mex/mexTrainDL.cpp:197: instantiated from here
./linalg/linalg.h:1084: error: explicit instantiation of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]' but no definition available
mex: compile of ' "dictLearn/mex/mexTrainDL.cpp"' failed.
The problem is not connected to the framework. Googling I have seen that I'm not the only one with this problem with matlab, but I don't know how to fix it. Thank you very much in advance for any help.
Mattia
UPDATE:
I've discovered that the error is produced by the following blocks of code
Block 1:
/// print the sparse matrix
template<typename T> inline void SpMatrix<T>::print(const string& name) const {
cerr << name << endl;
cerr << _m << " x " << _n << " , " << _nzmax << endl;
for (int i = 0; i<_n; ++i) {
for (int j = _pB[i]; j<_pE[i]; ++j) {
cerr << "(" <<_r[j] << "," << i << ") = " << _v[j] << endl;
}
}
};
Block 2
/// Print the matrix to std::cout
template <typename T> inline void Matrix<T>::print(const string& name) const {
std::cerr << name << std::endl;
std::cerr << _m << " x " << _n << std::endl;
for (int i = 0; i<_m; ++i) {
for (int j = 0; j<_n; ++j) {
printf("%10.5g ",static_cast<double>(_X[j*_m+i]));
// std::cerr << _X[j*_m+i] << " ";
}
printf("\n ");
//std::cerr << std::endl;
}
printf("\n ");
};
Block 3
template <typename T> void ShiftMatrix<T>::print(const string& name) const {
cerr << name << endl;
cerr << "Shift Matrix: " << _shifts << " shifts" << endl;
_inputmatrix->print(name);
};
And block 4
template <typename T> void DoubleRowMatrix<T>::print(const string& name) const {
cerr << name << endl;
cerr << "Double Row Matrix" << endl;
_inputmatrix->print(name);
};
and the error is always due to the first line of the above blocks, that is ...
cerr << name << endl;
Commenting the above line in the 4 blocks the compiling terminates successfully.
Does somebody know why this happens?
I solved this problem by adding the compile flag "-mmacosx-version-min=10.7" via the line
compile_flags=[compile_flags ' -mmacosx-version-min=10.7'];
in the SPAMS framework's compile.m immediately before the for block that calls mex.
This solution came from Trying to build muParser: error: explicit instantiation of 'std::basic_ostream but no definition available and Building libsigc++ fails (std::basic_ostream explicit instantiation) which appear to be the same problem with other packages.
I solved a similar problem by changing the MACOSX_DEPLOYMENT_TARGET='10.5' to '10.6' in mexopts.sh.