I see two ways of accessing a boost::optional variable:
The dereference operator on the variable
The variable itself
If I have this code snippet:
#include <boost/optional.hpp>
#include <iostream>
int main()
{
boost::optional<int> oi;
std::cout << oi << "\n";
}
(where oi is uninitialized) and compile it using "g++-4.9 /tmp/optional.cc" followed by ./a.out, I get 0,
but with this:
#include <boost/optional.hpp>
#include <iostream>
int main()
{
boost::optional<int> oi;
std::cout << *oi << "\n";
}
I get:
a.out: /usr/include/boost/optional/optional.hpp:631: boost::optional<T>::reference_type boost::optional<T>::get() [with T = int; boost::optional<T>::reference_type = int&]: Assertion `this->is_initialized()' failed.
Aborted (core dumped)
which is the expected behavior.
You must have been using an older version of Boost. Your first case triggered a conversion to bool; since the optional does not contain a value, the result of the conversion is false, which is printed as 0.
Newer versions (1.56-1.57) added an operator<< function template declaration to <boost/optional.hpp>
template<class CharType, class CharTrait, class T>
std::basic_ostream<CharType, CharTrait>&
operator<<(std::basic_ostream<CharType, CharTrait>& out, optional<T> const& v);
to catch this kind of mistakes and cause a linker error instead.
Note that including <boost/optional/optional_io.hpp> allows you to actually use the stream operators with optional, in which case optionals that do not contain a value are printed as --.
boost::optional<T> ostream helpers are actually available since boost 1.34. See http://www.boost.org/doc/libs/1_34_0/boost/optional/optional_io.hpp
Note that one needs to EXPLICITLY include <boost/optional/optional_io.hpp> to enable these helpers. It is NOT included by <boost/optional.hpp>.
Related
This code snippet (https://gcc.godbolt.org/z/hKDMxm):
#include <iostream>
#include <sstream>
using namespace std;
int main() {
auto s = (ostringstream{} << "string").str();
cout << s;
return 0;
}
compiles and runs as expected with msvc, but fails to compile with clang 9.0.0 and gcc 9.2 giving this error message:no member named 'str' in 'std::basic_ostream<char>'. Looking at https://en.cppreference.com/w/cpp/io/basic_ostringstream/str there is clearly str() member of ostringstream. Why clang and gcc are failing to compile this code?
there is clearly str() member of ostringstream
Yes, but according to cppreference this overload of << should return a reference to basic_ostream<...> rather than ostringstream.
libstdc++ (GCC's standard library) does exactly this, while libc++ (Clang's standard library) and MSVC's standard library behave incorrectly here, technically.
However, it seems there is an open defect report suggesting that the overload of << that works with rvalue streams should return the exact stream type that was passed to it. If it gets accepted, your code will be valid.
operator<< is member of std::ostream, and returns std::ostream& as described here
MSVC obviously has own overload this operator for std::ostringstream, what is not in standard
I ran into the same problem, and solved it with a wrapper class like this:
#include <sstream>
struct StreamHelper
{
std::ostringstream stream;
template< typename T >
StreamHelper& operator<<( const T& value )
{
stream << value; return *this;
}
std::string str() const
{
return stream.str();
}
operator std::string() const
{
return stream.str();
}
};
Then you can do your one-liner:
auto s = (StreamHelper() << "string1," << "string2").str();
If the compiler can figure out that the target type is a string, you don't need the .str() at the end and can use the implicit cast operator.
std::string s = (StreamHelper() << "string1," << "string2");
Why does the following code generate std::bad_cast exception?
#include <iostream>
#include <regex>
#include <string>
int main()
{
std::basic_string<char32_t> reg = U"^\\w";
try
{
std::basic_regex<char32_t> tagRegex(reg);
}
catch(std::exception &e)
{
std::cout << e.what() << std::endl;
}
return 0;
}
This sample on Ideone for convenience: https://ideone.com/Saea88
Using char or wchar instead of char32_t runs without throwing though (proof: https://ideone.com/OBlXed).
You can find here: http://en.cppreference.com/w/cpp/regex/regex_traits:
To use std::basic_regex with other character types (for example, char32_t), a user-provided trait class must be used.
so you would have to implement std::regex_traits<char32_t>
and to see why there is no definition for it see here: Why is there no definition for std::regex_traits<char32_t> (and thus no std::basic_regex<char32_t>) provided?
On GCC or Clang, the code compiles fine even with custom regex traits, but fails at runtime with std::bad_cast. If you've got yourself here, the issue comes from std::use_facet<std::ctype<char32_t>> throwing the error, because the current locale doesn't support it. You have to specialize std::ctype<char32_t> and set the global locale via std::locale::global to a new locale constructed using the old one and the specialized facet.
Lyrics:
I try to implement a task pool over MPI. So I need some kind of RPC but one that would work between different parts of my program, meaning processor A wants processor B to call function C with argument D. We can not pass pointers to functions between processes like we do with threads, so we need some wrapper container to hold our function pointers at each process instance. All inside one source file\one program... So I started wondering about How to store functional objects with different signature in a container. My API Idea back then was wrong - it is better to define all functions in function pool at that pool construction (at least it shall be much easier to implement). But while implementing I faced next trouble:
Problem:
Such simple code (function_types, mpl::vector, variant):
#include <boost/function_types/function_type.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/variant.hpp>
#include <iostream>
#include <string>
template <class T>
int append(T val)
{
std::cout << "hello";
return 0;
}
int main()
{
boost::variant<boost::function_types::function_type< boost::mpl::vector<int,int> >::type , boost::function_types::function_type< boost::mpl::vector<int,std::string> >::type > a;
return 0;
}
Will not compile falling with:
Error 1 error C2066: cast to function type is illegal c:\program files\boost\include\boost\variant\variant.hpp 1231 1
And looking at source we see:
this code block:
variant()
{
// NOTE TO USER :
// Compile error from here indicates that the first bound
// type is not default-constructible, and so variant cannot
// support its own default-construction.
//
new( storage_.address() ) internal_T0();
indicate_which(0); // zero is the index of the first bounded type
}
So I wonder: How to get around this error?
Also I tried:
#include <boost/function_types/function_type.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/variant.hpp>
#include <boost/function.hpp>
#include <iostream>
#include <string>
template <class T>
int append(T val)
{
std::cout << "hello";
return 1;
}
int main()
{
boost::variant< boost::function<int (std::string) >, boost::function<int (int) > > a;
a= &append<int>;
return 0;
}
Which fails with:
Error 1 error C2668: 'boost::detail::variant::make_initializer_node::apply<BaseIndexPair,Iterator>::initializer_node::initialize' : ambiguous call to overloaded function c:\program files\boost\include\boost\variant\variant.hpp 1330
Any Ideas on how to make boost.variant hold functions?
Of course we can play with shared pointers to functors like so:
#include <boost/variant.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <string>
template <class in, class out>
struct s_append
{
out operator()(in val) {
std::cout << "hello";
return out();
}
};
int main()
{
boost::variant<boost::shared_ptr<s_append<int, int> >, boost::shared_ptr< s_append<std::string, int> > > a;
boost::shared_ptr<s_append<int, int> > b(new s_append<int, int> );
a=b;
return 0;
}
and it would compile but resulting API sucks - you have to 1) create functors for all functions you want to use (meaning limit there use of current process scope); 2) use shared_pointers and so I don't really even get how to call functions nested that way (simple first guess (*a)(22); just won't compile =( and API starts to be as bad as we would have using Boost.Any).
Try inserting a dummy type as the first argument of the variant. As the comment you found explains, only the first type in the variant is used for the variant's own default constructor. You could use an empty struct type for this (struct NoFunction {};).
That said, you may have been onto something with the idea to use boost::functions as the types in the variant...they are default-constructible at least. I'm not sure what the other error you had from that approach was caused by, but just wanted to let you know you could pursue that angle more if you can't use the dummy-type workaround I mentioned.
I need to deserialize a std::vector<boost::variant<..>> with decoration supplied by other objects.
One of the things the "decoration" enables is a empty entry in the vector. I have hit a brick wall in my real implementation. However, I have managed to shrink wrap it. Code that compiles :
#include <string>
#include <boost/spirit/include/karma.hpp>
#include <boost/variant.hpp>
#include <boost/cstdint.hpp>
namespace karma = boost::spirit::karma;
typedef boost::variant<boost::int32_t, boost::int64_t> custom_variant;
int main()
{
using karma::generate;
custom_variant v;
std::string temp;
std::back_insert_iterator<std::string> x(temp);
std::cout << v;
karma::generate(x, karma::auto_, v);
}
The offending changes, which attempt to implement a "undefined" type, along with the required concept.
#include <string>
#include <boost/spirit/include/karma.hpp>
#include <boost/variant.hpp>
#include <boost/cstdint.hpp>
namespace karma = boost::spirit::karma;
struct undefined{};
std::ostream & operator<<(std::ostream & out, undefined const & undefined)
{
return out;
}
typedef boost::variant<undefined,boost::int32_t, boost::int64_t> custom_variant;
int main()
{
using karma::generate;
custom_variant v;
std::string temp;
std::back_insert_iterator<std::string> x(temp);
std::cout << v;
karma::generate(x, karma::auto_, v);
}
If I comment out the karma::generate step, std::cout is a valid expression (Boost::variant OutputStreamable). Spirit requires that generators be given types which are OutputStreamable(spirit::karma OutputStreamable) and the variant above should be OutputStreamable since I have made the undefined typeOutputStreamable as a no-op.
What gives ? :(
I'm really beginning to question weather the C++ template mechanism is worth it when using libraries with > 2 levels of template indirection. Perhaps I should go back to straight-c.
Edit 1:
Ok, Clang gave me a sensible first error...
error: no type named 'properties' in 'boost::spirit::karma::no_auto_mapping_exists'
Now I got to figure out how to map undefined as a no-op to get a clean conversion. This spirit documentation entry (and this in specific) describes what I need to look into. Is there a generic undefined type provided by spirit or one defined in boost, that spirit already maps as a no-op ?
Edit 2:
std::vector<boost::optional<boost::variant<..>>> is beginning to look quite appealing since spirit provides type-deduction for them.
I'd suggest to use spirit::unused_type for that purpose as it already is 'known' to Spirit and it has an operator<<() predefined (but any other type will do) - not that you really need that operator for Karma in the first place.
In addition, you have to provide a specialization for create_generator (as you suspected):
namespace boost { namespace spirit { namespace traits
{
template <>
struct create_generator<spirit::unused_type>
{
typedef spirit::karma::eps_type type;
static type call()
{
return spirit::karma::eps;
}
};
}}}
which will map unused_type to karma::eps. This seems to be exactly what you need as eps eats the attribute without generating anything, while succeeding always. If you go this route you will not need to utilize optional<>.
I have a boost recursive variant as below. When I compare two recursive variant object using assert, it works fine but with EXPECT_EQ, it gives compile error.
typedef boost::make_recursive_variant<bool, boost::uint8_t, boost::uint32_t,
boost::int32_t, double, std::string, boost::uuids::uuid>::type rvariant_type;
variant_type b1 = true;
rvariant_type b2 = true;
assert(b1 == b2); //work fine
EXPECT_EQ(b1,b2); //gives compiler error.
EXPECT_EQ(boost::get<bool>(b1), boost::get<bool>(b2)); //works fine
boost/v1.46.1/include/boost/variant/detail/variant_io.hpp:64: error: no match for ‘operator<<’ in ‘((const boost::detail::variant::printer > >*)this)->boost::detail::variant::printer > >::out_ << operand’
gtest makes heavy use of streams for output but it seems that the boost::variant support for printing via an overloaded operator<< is very limited, if not nonexistant.
Take a look at this:
#include <boost/variant.hpp>
#include <boost/cstdint.hpp>
#include <boost/uuid/uuid.hpp>
#include <iostream>
typedef boost::make_recursive_variant<bool, boost::uint8_t, boost::uint32_t,
boost::int32_t, double, std::string, boost::uuids::uuid>::type rvariant_type;
int main() {
rvariant_type v1 = true;
std::cout << v1 << std::endl;
return 0;
}
This very short program gives the same compilation error you got from gtest.
Supplementing it with this:
std::ostream& operator<<(std::ostream& out, const rvariant_type& p) {
return out << boost::get<bool>(p);
}
makes my test compile, I'll take a look if I can make your example work as well.
UPDATE: I just compiled and successfully ran a test based on your code after putting the above-mentioned operator<<, so the lack of an operator<< is precisely what was causing it.