I have a "dictionary" std::map<std::string, boost::any> (or std::any, if you want) that can possibly be nested. Now, I would like to display the map. Since boost::any obviously doesn't play nicely with <<, things are getting a little nasty. So far, I'm checking the type, cast it, and pipe the cast to cout:
for (const auto &p: map) {
std::cout << std::string(indent + 2, ' ') << p.first << ": ";
if (p.second.type() == typeid(int)) {
std::cout << boost::any_cast<int>(p.second);
} else if (p.second.type() == typeid(double)) {
std::cout << boost::any_cast<double>(p.second);
} else if (p.second.type() == typeid(std::string)) {
std::cout << boost::any_cast<std::string>(p.second);
} else if (p.second.type() == typeid(const char*)) {
std::cout << boost::any_cast<const char*>(p.second);
} else if (p.second.type() == typeid(std::map<std::string, boost::any>)) {
show_map(
boost::any_cast<std::map<std::string, boost::any>>(p.second),
indent + 2
);
} else {
std::cout << "[unhandled type]";
}
std::cout << std::endl;
}
std::cout << std::string(indent, ' ') << "}";
This prints, for example
{
fruit: banana
taste: {
sweet: 1.0
bitter: 0.1
}
}
Unfortunately, this is hardly scalable. I'd have to add another else if clause for every type (e.g., float, size_t,...), which is why I'm not particularly happy with the solution.
Is there a way to generalize the above to more types?
One thing you can do to lessen (but not remove) the pain is to factor the type determination logic into one support function, while using static polymorphism (specifically templates) for the action to be applied to the values...
#include <iostream>
#include <boost/any.hpp>
#include <string>
struct Printer
{
std::ostream& os_;
template <typename T>
void operator()(const T& t)
{
os_ << t;
}
};
template <typename F>
void f_any(F& f, const boost::any& a)
{
if (auto p = boost::any_cast<std::string>(&a)) f(*p);
if (auto p = boost::any_cast<double>(&a)) f(*p);
if (auto p = boost::any_cast<int>(&a)) f(*p);
// whatever handling for unknown types...
}
int main()
{
boost::any anys[] = { std::string("hi"), 3.14159, 27 };
Printer printer{std::cout};
for (const auto& a : anys)
{
f_any(printer, a);
std::cout << '\n';
}
}
(With only a smidge more effort, you could have the type-specific test and dispatch done for each type in a variadic template parameter pack, simplifying that code and the hassle of maintaining the list. Or, you could just use a preprocessor macro to churn out the if-cast/dispatch statements....)
Still - if you know the set of types, a boost::variant is more appropriate and already supports similar operations (see here).
Yet another option is to "memorise" how to do specific operations - such as printing - when you create your types:
#include <iostream>
#include <boost/any.hpp>
#include <string>
#include <functional>
struct Super_Any : boost::any
{
template <typename T>
Super_Any(const T& t)
: boost::any(t),
printer_([](std::ostream& os, const boost::any& a) { os << boost::any_cast<const T&>(a); })
{ }
std::function<void(std::ostream&, const boost::any&)> printer_;
};
int main()
{
Super_Any anys[] = { std::string("hi"), 3.14159, 27 };
for (const auto& a : anys)
{
a.printer_(std::cout, a);
std::cout << '\n';
}
}
If you have many operations and want to reduce memory usage, you can have the templated constructor create and store a (abstract-base-class) pointer to a static-type-specific class deriving from an abstract interface with the operations you want to support: that way you're only adding one pointer per Super_Any object.
Since you're already using Boost you could consider boost::spirit::hold_any.
It already has pre-defined streaming operators (both operator<<() and operator>>()).
Just the embedded type must have the corresponding operator defined, but in your use context this seems to be completely safe.
Despite being in the detail namespace, hold_any is quite widespread and almost a ready-to-use boost:any substitute (e.g. Type Erasure - Part IV, Why you shouldn’t use boost::any)
A recent version of Boost is required (old versions had a broken copy assignment operator).
Related
I want to explore how I can use std::any instead of void * or such constructs for message passing. So I created an example code to test this - see below.
The use of std::any looks nice, but I want to switch through the types to check which type the std::any is. It might no be possible, and I know I can use a if/elseif... block instead, but it would be very nice if I can create a switch statement so that if I use this in real code with 10-20 different types it will be more readable.
#include <string>
#include <iostream>
#include <sstream>
#include <any>
#include <typeindex>
struct ints { int a{1}; int b{2}; };
struct strings { std::string a{"string1"}; std::string b{"string2"}; };
void send_msg(std::any item)
{
switch (item.type().hash_code()) // <------- HERE
{
case typeid(ints).hash_code(): // <------- HERE
std::cout << "ints" << std::endl;
break;
case typeid(strings).hash_code():
std::cout << "strings" << std::endl;
break;
default:
std::cout << "unknown type\n";
}
}
int main()
{
strings s;
send_msg(s);
ints i;
send_msg(i);
}
live example: https://godbolt.org/z/xPrMYM
I can't switch on the type_info returned by std::any::type, but I can switch on the hash_code() of the type_info, but that is not a constexpr I hoped it was though!
so I also tried getting the address of the type info and a few other tricks that I could find. But no luck so far...
Is there such a way?
I would also suggest a variant here if possible but for the concrete question:
If you can use boost and C++17 is your referred standard: They provide an extended typeid handling that can also be used for several compile time checks, see
https://www.boost.org/doc/libs/1_67_0/boost/type_index/ctti_type_index.hpp
Its underlying rawType is a const char* constexpr and the typeIndex itself can be used as a perfect replacement for std::type_info. Since the standard guarantees unique addresses for these type identifiers, even a simple address comparison should be possible here (not sure why this simplification is currently out commented inside the boost headers though).
To be usable with any, you might have to wrap it or to use a simple own any type.
What you're asking is std::visit, but with std::any
template<typename... Ts, typename F>
bool visit(F&& f, std::any x)
{
auto result = ((x.type() == typeid(Ts) ?
(std::forward<F>(f)(*std::any_cast<Ts>(&x)), true) : false) || ...);
return result;
}
Since the std::any might contain anything, the visit might fail at runtime, which is why you certainly need some way to report the error†.
Use as
bool send_msg(std::any x)
{
auto f = [](auto&& x){
std::cout << x << '\n';
};
return visit<std::string, int>(f, x);
}
But then, using std::variant is just simpler
void send_msg(std::variant<std::string, int> x)
{
auto f = [](auto&& x){
std::cout << x << '\n';
};
visit(f, x);
}
†The complete visit implementation would be a bit more complicated.
Let's say that I have a function: pair<int, int> foo() I want to directly output both elements of this without using a temporary.
Is there a way that I can output this, or maybe convert it into a string to output? Could I perhaps use tie to do this?
Here's what I'm trying to do with the temporary:
const auto temporary = foo();
cout << temporary.first << ' ' << temporary.second << endl;
In c++17 standard, you can use structured binding declaration
std::pair<int, int> get_pair()
{
return {10, 20};
}
int main()
{
auto [x, y] = get_pair();
std::cout << x << " " << y << std::endl;
return 0;
}
No. You can't write that function without using a non-temporary. If you really need to, you should probably change the structure of your code. Technically, you could also use a global variable (although I strongly do not recommend this). I don't think tie would work for what you want it for either.
You can create a small class that wraps the std::pair, and enable output streams to print it via operator<<:
template<typename PairT>
struct printable {
const PairT& p;
printable(const PairT& p)
: p{p}
{}
};
template<typename CharT, typename PairT>
std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& out, const printable<PairT>& pair) {
out << pair.p.first << ' ' << pair.p.second;
return out;
}
Then you can use it like this:
auto foo() {
return std::pair<int, int>(1, 2);
}
int main() {
std::cout << printable(foo());
}
Live example
Of course, you could also just enable the printing directly for an std::pair...
template<typename CharT, typename A, typename B>
std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& out, const std::pair<A, B>& pair) {
out << pair.first << ' ' << pair.second;
return out;
}
// (...)
std::cout << foo(); // And this would work just fine
... but I don't really recommend it, specially on a header, since you would be basically changing behavior of standard types and your colleagues (or yourself, in the future) may be confused by it.
I have a "dictionary" std::map<std::string, boost::any> (or std::any, if you want) that can possibly be nested. Now, I would like to display the map. Since boost::any obviously doesn't play nicely with <<, things are getting a little nasty. So far, I'm checking the type, cast it, and pipe the cast to cout:
for (const auto &p: map) {
std::cout << std::string(indent + 2, ' ') << p.first << ": ";
if (p.second.type() == typeid(int)) {
std::cout << boost::any_cast<int>(p.second);
} else if (p.second.type() == typeid(double)) {
std::cout << boost::any_cast<double>(p.second);
} else if (p.second.type() == typeid(std::string)) {
std::cout << boost::any_cast<std::string>(p.second);
} else if (p.second.type() == typeid(const char*)) {
std::cout << boost::any_cast<const char*>(p.second);
} else if (p.second.type() == typeid(std::map<std::string, boost::any>)) {
show_map(
boost::any_cast<std::map<std::string, boost::any>>(p.second),
indent + 2
);
} else {
std::cout << "[unhandled type]";
}
std::cout << std::endl;
}
std::cout << std::string(indent, ' ') << "}";
This prints, for example
{
fruit: banana
taste: {
sweet: 1.0
bitter: 0.1
}
}
Unfortunately, this is hardly scalable. I'd have to add another else if clause for every type (e.g., float, size_t,...), which is why I'm not particularly happy with the solution.
Is there a way to generalize the above to more types?
One thing you can do to lessen (but not remove) the pain is to factor the type determination logic into one support function, while using static polymorphism (specifically templates) for the action to be applied to the values...
#include <iostream>
#include <boost/any.hpp>
#include <string>
struct Printer
{
std::ostream& os_;
template <typename T>
void operator()(const T& t)
{
os_ << t;
}
};
template <typename F>
void f_any(F& f, const boost::any& a)
{
if (auto p = boost::any_cast<std::string>(&a)) f(*p);
if (auto p = boost::any_cast<double>(&a)) f(*p);
if (auto p = boost::any_cast<int>(&a)) f(*p);
// whatever handling for unknown types...
}
int main()
{
boost::any anys[] = { std::string("hi"), 3.14159, 27 };
Printer printer{std::cout};
for (const auto& a : anys)
{
f_any(printer, a);
std::cout << '\n';
}
}
(With only a smidge more effort, you could have the type-specific test and dispatch done for each type in a variadic template parameter pack, simplifying that code and the hassle of maintaining the list. Or, you could just use a preprocessor macro to churn out the if-cast/dispatch statements....)
Still - if you know the set of types, a boost::variant is more appropriate and already supports similar operations (see here).
Yet another option is to "memorise" how to do specific operations - such as printing - when you create your types:
#include <iostream>
#include <boost/any.hpp>
#include <string>
#include <functional>
struct Super_Any : boost::any
{
template <typename T>
Super_Any(const T& t)
: boost::any(t),
printer_([](std::ostream& os, const boost::any& a) { os << boost::any_cast<const T&>(a); })
{ }
std::function<void(std::ostream&, const boost::any&)> printer_;
};
int main()
{
Super_Any anys[] = { std::string("hi"), 3.14159, 27 };
for (const auto& a : anys)
{
a.printer_(std::cout, a);
std::cout << '\n';
}
}
If you have many operations and want to reduce memory usage, you can have the templated constructor create and store a (abstract-base-class) pointer to a static-type-specific class deriving from an abstract interface with the operations you want to support: that way you're only adding one pointer per Super_Any object.
Since you're already using Boost you could consider boost::spirit::hold_any.
It already has pre-defined streaming operators (both operator<<() and operator>>()).
Just the embedded type must have the corresponding operator defined, but in your use context this seems to be completely safe.
Despite being in the detail namespace, hold_any is quite widespread and almost a ready-to-use boost:any substitute (e.g. Type Erasure - Part IV, Why you shouldn’t use boost::any)
A recent version of Boost is required (old versions had a broken copy assignment operator).
First of all I want a normal enumeration instead of a bit-based enumeration, because the amount of different enums will be beyond any integral type. I also want to take advantage of the type safety of C++11 enum class. To do so, the natural choice would be std::bitset, however I have no idea how to bind those two together.
A custom bitset would be needed? How to go around the implementation of such a class?
Since enum classes are wrappers for enums, you can cast them to underlying type. And using some private inheritance you can selectively import some functionalities from C++ stdlib classes without worrying about Liskov's principle. Composition resulted in clearer code. Using these functionalities, we can wrap std::bitset. Following code contains only subset of functionalites, but it can be expanded further.
There's a problem with max value - that you can't get maximum value of enum class (or am I wrong?). So I added EnumTraits. Now users are required to specialize EnumTraits with const value max equal to the max value of enum before class can be used.
#include <bitset>
#include <type_traits>
template<typename T>
struct EnumTraits;
template<typename T>
class EnumClassBitset
{
private:
std::bitset<static_cast<typename std::underlying_type<T>::type>(EnumTraits<T>::max)> c;
typename std::underlying_type<T>::type get_value(T v) const
{
return static_cast<typename std::underlying_type<T>::type>(v);
}
public:
EnumClassBitset() : c()
{
}
bool test(T pos) const
{
return c.test(get_value(pos));
}
EnumClassBitset& reset(T pos)
{
c.reset(get_value(pos));
return *this;
}
EnumClassBitset& flip(T pos)
{
c.flip(get_value(pos));
return *this;
}
};
enum class BitFlags
{
False,
True,
FileNotFound,
Write,
Read,
MaxVal
};
template<>
struct EnumTraits<BitFlags>
{
static const BitFlags max = BitFlags::MaxVal;
};
#include <iostream>
int main()
{
EnumClassBitset<BitFlags> f;
f.flip(BitFlags::True);
f.flip(BitFlags::FileNotFound);
//f.flip(2); //fails to compile
std::cout << "Is False? " << f.test(BitFlags::False) << "\n";
std::cout << "Is True? " << f.test(BitFlags::True) << "\n";
std::cout << "Is FileNotFound? " << f.test(BitFlags::FileNotFound) << "\n";
std::cout << "Is Write? " << f.test(BitFlags::Write) << "\n";
std::cout << "Is Read? " << f.test(BitFlags::Read) << "\n";
}
Since enums don't have much functionality unfortunately, and what is more, C++11 with enum classes don't improve the situation, some programmers use static map wrapped in a class. Definitely a good read.
I have a Map std::map<std::string, boost::any>, which comes from the boost::program_options package. Now I would like to print the content of that map:
for(po::variables_map::const_iterator it = vm.begin(); it != vm.end(); ++it) {
std::cerr << it->first << ": " << it->second << std::endl;
}
Unfortunately, that is not possible because boost::any doesn't have an operator<< defined.
What is the easiest way to print that map?
I could define my own output operator for any that automatically tries to cast each any to an int, then double, then string, etc., each time ignoring errors and trying to cast until the cast is successful and I can print as the specified type.
But there should be an easier method in Boost? I'd need something like a reverse lexical_cast...
You could use boost::spirit::hold_any instead. It's defined here:
#include <boost/spirit/home/support/detail/hold_any.hpp>
and is fully compatible with boost::any. This class has two differences if compared to boost::any:
it utilizes the small object optimization idiom and a couple of other optimization tricks, making spirit::hold_any smaller and faster than boost::any
it has the streaming operators (operator<<() and operator>>()) defined, allowing to input and output a spirit::hold_any seemlessly.
The only limitation is that you can't input into an empty spirit::hold_any, but it needs to be holding a (possibly default constructed) instance of the type which is expected from the input.
If you can change boost::any to another type, you can use Boost.TypeErasure. If you ever wanted to create a type that's like any, but only supporting types that support these particular operations at compile time, then this is just for you.
#include <boost/type_erasure/operators.hpp>
#include <boost/type_erasure/any.hpp>
#include <boost/mpl/vector.hpp>
#include <random>
#include <iostream>
namespace te = boost::type_erasure;
typedef te::any<boost::mpl::vector<
te::copy_constructible<>,
te::destructible<>,
te::ostreamable<>
>> streamable_any;
int main()
{
streamable_any i(42);
streamable_any d(23.5);
std::mt19937 mt;
streamable_any r(mt);
std::cout << i << "\n" << d << "\n" << r << "\n";
}
Live On Coliru
Unfortunately, with any the only way is to use the type() method to determine what is contained within any, then cast it with any_cast. Obviously you must have RTTI enabled, but you probably already do if you're using any:
for(po::variables_map::const_iterator it = vm.begin(); it != vm.end(); ++it) {
if(typeid(float) == it->second.type()) {
std::cerr << it->first << ": " << any_cast<float>(it->second) << std::endl;
}
else if(typeid(int) == it->second.type()) {
std::cerr << it->first << ": " << any_cast<int>(it->second) << std::endl;
}
...
}
Define some aux function to output to stream:
template<class T>
bool out_to_stream(std::ostream& os, const boost::any& any_value)
{
try {
T v = boost::any_cast<T>(any_value);
os << v;
return true;
} catch(boost:: bad_any_cast& e) {
return false;
}
}
You can define a special formatting for some types
template<>
bool out_to_stream<std::string>(std::ostream& os, const boost::any& any_value)
{
try {
std::string v(std::move(boost::any_cast<std::string>(any_value)));
os << "'" << v << "'";
return true;
} catch(boost:: bad_any_cast& e) {
return false;
}
}
or
template<>
bool out_to_stream<bool>(std::ostream& os, const boost::any& any_value)
{
try {
os << ((boost::any_cast<bool>(any_value))? "yes" : "no");
return true;
} catch(boost:: bad_any_cast& e) {
return false;
}
}
Then define an output operator for boost::any where you list all types you want to try to cast and output
std::ostream& operator<<(std::ostream& os, const boost::any& any_value)
{
//list all types you want to try
if(!out_to_stream<int>(os, any_value))
if(!out_to_stream<double>(os, any_value))
if(!out_to_stream<bool>(os, any_value))
if(!out_to_stream<std::string>(os, any_value))
os<<"{unknown}"; // all cast are failed, an unknown type of any
return os;
}
And then for a value_type:
std::ostream& operator<<(std::ostream& os, const boost::program_options::variable_value& cmdline_val)
{
if(cmdline_val.empty()){
os << "<empty>";
} else {
os<<cmdline_val.value();
if(cmdline_val.defaulted())
os << "(default)";
}
return os;
}
The list of type switches proposed in other answers can be improved with a loop over a type list using Boost MPL (see documentation of mpl::for_each and mpl::vector). The following code defines an operator<< for any boost::any that is given in the type list SupportedTypes and throws an exception otherwise.
#include <stdexcept>
#include <iostream>
#include <string>
#include <cstdint>
#include <boost/any.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/vector.hpp>
class StreamInserter
{
private:
std::ostream& os_;
const boost::any &v_;
mutable bool has_printed_;
public:
struct UnsupportedType {};
StreamInserter(std::ostream& os, const boost::any &v)
: os_(os), v_(v), has_printed_(false) {}
template <typename T>
void operator()(const T&) const
{
if (!has_printed_ && v_.type() == typeid(T))
{
os_ << boost::any_cast<T>(v_);
has_printed_ = true;
}
}
void operator()(const UnsupportedType&) const
{
if (!has_printed_)
throw std::runtime_error("unsupported type");
}
};
std::ostream& operator<<(std::ostream& os, const boost::any& v)
{
typedef boost::mpl::vector<float, double, int8_t, uint8_t, int16_t, uint16_t,
int32_t, uint32_t, int64_t, uint64_t, std::string, const char*,
StreamInserter::UnsupportedType> SupportedTypes;
StreamInserter si(os, v);
boost::mpl::for_each<SupportedTypes>(si);
return os;
}
int main(int, char**)
{
std::cout << boost::any(42.0) << std::endl;
std::cout << boost::any(42) << std::endl;
std::cout << boost::any(42UL) << std::endl;
std::cout << boost::any("42") << std::endl;
std::cout << boost::any(std::string("42")) << std::endl;
std::cout << boost::any(bool(42)) << std::endl; // throws exception
}
I think you have to cover each possible case of objects you have to print... Or use boost::variant.
EDIT: Sorry, I thought I shall write WHY.
The reason why I think that is because, looking at any source code, it seems to rely on the fact that YOU provide the types when inserting and getting data. When you insert, data is automatically detected by the compiler, so you don't have to specify it. But when you get the data, you shall use any_cast, because you're not sure of the data type you're getting.
If it worked in a different way and data type was sure, I think that would be no need for any_cast :)
Instead, variant have a limited set of possible data types, and this information is somewhat registered, giving you the ability to iterate in a generic way a variant container.
If you need this kind of manipulation - iterating a generic set of values - I think you shall use variant.
Try using xany https://sourceforge.net/projects/extendableany/?source=directory xany class allows to add new methods to any's existing functionality. By the way there is a example in documentation which does exactly what you want.
Rather than re-writing my class to use boost::spirit::hold_any, I created a way to stream boost::any, similar to what manifest suggested, but just in one place.
ostream& operator<<(ostream& _os, const boost::any& _any)
{
// only define simple type conversions
if (_any.type() == typeid(int))
_os << boost::any_cast<int>(_any);
/*any other types you use...*/
}
Rather cumbersome, but it allows me to stream a boost::any variable anywhere in my code.
How about being able to construct a boost::spirit::hold_any from a boost:any?
A little late for this party, but anyone that may be interested can also use std::tuple and a std::for_each-like template that iterates over a tuple.
This is based on the answer from ingomueller.net in this thread.
I had a recent case where I created a property map (reading configuration values, mainly fundamental types, from an XML file and inserting them into an std::unordered_map, where the value type is of type any. For debugging purposes I wanted to be able to print the entire map with its keys and values along with the type of the value.
In that project I am not using Boost at all, I used my own any implementation, but its very similar to boost::any.
The insertion operator basically looks like this:
template <typename TChar>
inline std::basic_ostream<TChar>&
operator<< (std::basic_ostream<TChar>& os, const sl::common::any& v)
{
// Types that we support with sl::common::any.
std::tuple<
float, double, bool,
int8_t, uint8_t,
int16_t, uint16_t,
int32_t, uint32_t,
int64_t, uint64_t,
std::wstring, const wchar_t*,
StreamInserter::UnsupportedType> t;
// Prepare ostream for printing a value of type any
StreamInserter si(os, v);
// Iterate over all types in tuple t. If the last type(UnsupportedType) is
// reached, given v is unsupported.
for_each(t, si);
return os;
}
The for_each template looks like this (C++14):
template <typename Tuple, typename F, std::size_t ...Indices>
constexpr void for_each_impl(Tuple&& tuple, F&& f, std::index_sequence<Indices...>) {
using swallow = int[];
(void)swallow{1,
(f(std::get<Indices>(std::forward<Tuple>(tuple))), void(), int{})...
};
}
template <typename Tuple, typename F>
constexpr void for_each(Tuple&& tuple, F&& f) {
constexpr std::size_t N = std::tuple_size<std::remove_reference_t<Tuple>>::value;
for_each_impl(std::forward<Tuple>(tuple), std::forward<F>(f),
std::make_index_sequence<N>{});
}
With this just use the StreamInserter class or something similar shown in Ingos answer.
Hope this helps.