I want to use boost to join string with ",". But I have a vector of shared_ptr which I need to transform to a string.
(dumb way to do it is to use boost::transform to convert my shared pointer to a vector of strings).
But I wanted to do something like this.
NOTE: I am using VS2012 (and gcc 4.5.3 for Linux builds) and boost 1.48.0
C++ code.
std::string A::returnConcatString() const
{
return boost::algorithm::join( sharedPtrList() | boost::adaptors::transformed(
[](B::ConstPtr obj )->std::string
{
return ( boost::format( "%s:%s" ) % obj->string1() % obj->string2() ).str();
} ),
",");
}
(BTW what happends if I use an anonymous function instead of using string2()? )
HPP Code.
class A
{
public:
/***code***/
vector< B::ConstPtr > sharedPtrList() const;
std::string returnConcatString() const;
}
class B
{
public:
typedef boost::shared_ptr<const B> ConstPtr;
std::string string1() const;
std::string string2() const;
}
Is there a better way to do this? Can anyone please help me understand my issue?
Also, I came across this link http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3594.html (Which is exactly what I want to mimic)
When I compile this code I get an error.
C:\temp\tools\Windows\Boost\1.48.0\boost/utility/result_of.hpp(79): error C2903: 'result' : symbol is neither a class template nor a function template
C:\temp\tools\Windows\Boost\1.48.0\boost/utility/result_of.hpp(87) : see reference to class template instantiation 'boost::detail::result_of_nested_result<F,FArgs>' being compiled
with
[
F=balh::`anonymous-namespace'::<lambda0>,
FArgs=balh::`anonymous-namespace'::<lambda0> (const boost::shared_ptr<const balh::B> &)
]
C:\temp\tools\Windows\Boost\1.48.0\boost/utility/detail/result_of_iterate.hpp(33) : see reference to class template instantiation 'boost::detail::tr1_result_of_impl<F,FArgs,HasResultType>' being compiled
with
[
F=balh::`anonymous-namespace'::<lambda0>,
FArgs=balh::`anonymous-namespace'::<lambda0> (const boost::shared_ptr<const balh::B> &),
HasResultType=false
]
C:\temp\tools\Windows\Boost\1.48.0\boost/utility/detail/result_of_iterate.hpp(81) : see reference to class template instantiation 'boost::tr1_result_of<F>' being compiled
with
[
F=balh::`anonymous-namespace'::<lambda0> (const boost::shared_ptr<const balh::B> &)
]
C:\temp\tools\Windows\Boost\1.48.0\boost/mpl/eval_if.hpp(41) : see reference to class template instantiation 'boost::result_of<F>' being compiled
EDIT: Thanks to an [utnapistim] idea. I am using this for now. But I really wanted to write a one-liner :).
I ended up doing this.
std::string ret;
std::for_each ( array.begin(), array.end(), [&ret](B::ConstPtr firmware)
{
ret.append( ( boost::format( "[%s:%s]" ) % firmwareTypeToString( firmware->firmwareType() ) % firmware->version() ).str() );
}
);
I'd just write it like this:
std::string returnConcatString() const {
std::ostringstream os;
for(auto& b : sharedPtrList)
os << b->string1() << ':' << b->string2() << ',';
auto s = os.str();
if (!s.empty())
s.resize(s.size()-1);
return s; // moves
}
Amazingly, the compile times are better, and the runtime will be a lot better than your code would achieve.
See it Live On Coliru
And if you really cared about performance, I'd suggest Boost Karma:
std::string returnConcatString() const {
if (sharedPtrList.empty())
return {};
std::string result;
result.reserve(20 * sharedPtrList.size()); // average length preallocate?
auto out = back_inserter(result);
namespace k = boost::spirit::karma;
for(auto& b : sharedPtrList)
k::generate(out, k::string << ':' << k::string << ',', b->string1(), b->string2());
result.resize(result.size()-1);
return result; // moves
}
See it Live On Coliru too
A performance comparison:
As you can see, the stringstream approach is only bad at small collections.
Raw data and benchmark code
I use this:
/*
* File: ostream_join_iterator.hpp
* Author: utnapistim :)
*
* Created on July 13, 2013, 1:14 AM
*/
#ifndef OSTREAM_JOIN_ITERATOR_HPP
#define OSTREAM_JOIN_ITERATOR_HPP
/**
* #brief Implements join functionality directing into an ostream
*
* This class provides an iterator for writing into an ostream.
* The type T is the only type written by this iterator and there must
* be an operator << (T) defined.
*
* #remarks This class implements functionality similar to
* std::ostream_iterator except it does not print a separator after the
* last element.
*
* #param Tp The type to write to the ostream.
* #param CharT The ostream char_type.
* #param Traits The ostream char_traits.
*/
template<typename T, typename C=char, typename Tr=std::char_traits<C> >
class ostream_join_iterator
: public std::iterator<std::output_iterator_tag, void, void, void, void>
{
public:
typedef C char_type;
typedef Tr traits_type;
typedef std::basic_string<C, Tr> splitter_type;
typedef std::basic_ostream<C, Tr> ostream_type;
private:
ostream_type *out_;
splitter_type splitter_;
bool at_first_;
public:
ostream_join_iterator(ostream_type& out)
: out_{&out}
, splitter_{}
, at_first_{true}
{
}
/**
* Construct from an ostream.
*
* #remarks The delimiter is not copied, and thus must not be destroyed
* while this iterator is in use.
*
* #param out Underlying ostream to write to.
* #param splitter CharT delimiter string to insert.
*/
ostream_join_iterator(ostream_type& out, const char_type* splitter)
: out_{&out}
, splitter_{splitter}
, at_first_{true}
{
}
/// Copy constructor.
ostream_join_iterator(const ostream_join_iterator& other)
: out_{other.out_}
, splitter_{other.splitter_}
, at_first_{other.at_first_}
{
}
ostream_join_iterator& operator=(const T& value)
{ // add separator before the value, if not at first element
if((not splitter_.empty()) and (not at_first_))
*out_ << splitter_;
*out_ << value;
at_first_ = false;
return *this;
}
ostream_join_iterator& operator=(ostream_join_iterator temp)
{
using std::swap;
swap(out_, temp.out_);
swap(splitter_, temp.splitter_);
swap(at_first_, temp.at_first_);
return *this;
}
ostream_join_iterator&
operator*() {
return *this;
}
ostream_join_iterator&
operator++() {
return *this;
}
ostream_join_iterator&
operator++(int) {
return *this;
}
};
template <typename T> using join = ostream_join_iterator<T>;
template <typename T> using wjoin = ostream_join_iterator<T, wchar_t>;
#endif /* OSTREAM_JOIN_ITERATOR_HPP */
Usage:
using namespace std;
ostringstream sql;
sql << "SELECT ";
transform(fields_.begin(), fields_.end(), join<string>{sql, ", "},
[](const field& f) { return f.escaped_name(); });
sql << " FROM " << name_;
The transform call can easily be paced into a convenience function.
Related
I'm trying to create and return a boost:any_range that contains only one object (I don't know if that's the core problem) but I get the following errors:
error C2893: Failed to specialize function template
'range_iterator<C,void>::type boost::range_adl_barrier::begin(T &)'
note: With the following template arguments:
note: 'T=const WrappedRange'
error C2672: 'end': no matching overloaded function found
error C2893: Failed to specialize function template
'range_iterator<C,void>::type boost::range_adl_barrier::end(T &)'
note: With the following template arguments: note: 'T=const
WrappedRange'
Below you can find the relevant code snippets:
That's the function I want to call and which fails during compiling:
const HandleRange BasicCollection::GetPartHandles() const
{
return HandleRange
//return -> also tried this
{
Handle(GenericHandleManager::CreatePartHandleValue(GenericHandleManager::GetPartIdx(_collectionHandle)))
};
}
Somehow this works, but that's not really clean:
const HandleRange BasicCollection::GetPartHandles() const
{
auto container = { _collectionHandle };
return container | boost::adaptors::transformed([collectionHandle = _collectionHandle](const auto & index_value)
{
return HandleRange::value_type
{
Handle(GenericHandleManager::CreatePartHandleValue(GenericHandleManager::GetPartIdx(collectionHandle)))
};
});
}
That's the HandleRange type that shall be returned:
/**
* Defines an alias representing a boost range for handles.
*/
using HandleRange = boost::any_range<Handle, boost::forward_traversal_tag, const Handle>;
The used Handle object:
class Handle
{
public:
/**
* Construct a handle from a handle value.
* #param value The handle's value.
*/
inline explicit Handle(int_fast64_t value) noexcept : _value(value)
{
}
...
}
Thanks for any suggestions!
Somehow this works, but that's not really clean
That should not compile without diagnostics, as auto is deduced as std::initializer_list<Handle>.
That approach invokes Undefined Behaviour because the initializer list doesn't exist after returning.
Solutions
The any_range should be able to return an iterator range.
Pointers are iterators.
Any single object o can be seen as a range [&o, &o + 1). That's a valid iterator range.
Combining these would already be a solution if GenericHandleManager::CreatePartHandleValue(...) returns a reference:
const HandleRange BasicCollection::GetPartHandles() const {
Handle& h =
GenericHandleManager::CreatePartHandleValue(
GenericHandleManager::GetPartIdx(_collectionHandle));
return boost::make_iterator_range(&h, &h + 1));
}
Singleton Ranges
If it returns a temporary, though, you'll need to make that "a range":
template <typename T>
struct SingletonRange : boost::iterator_range<T*> {
T val;
SingletonRange(T val)
: boost::iterator_range<T*>(std::addressof(val), std::addressof(val) + 1),
val(std::move(val))
{ }
};
Now you can safely¹ write (even though CreatePartHandleValue returns a temporary):
HandleRange BasicCollection::GetPartHandles() const {
Handle h =
GenericHandleManager::CreatePartHandleValue(
GenericHandleManager::GetPartIdx(_collectionHandle));
return SingletonRange<Handle> {h};
}
Full Demo
Live On Coliru
#include <boost/range/iterator_range.hpp>
template <typename T>
struct SingletonRange : boost::iterator_range<T*> {
T val;
SingletonRange(T val)
: boost::iterator_range<T*>(std::addressof(val), std::addressof(val) + 1),
val(std::move(val))
{ }
};
struct Handle{};
struct GenericHandleManager {
static int GetPartIdx(Handle) { return 42; }
static Handle CreatePartHandleValue(int) { return {}; }
};
#include <boost/range/any_range.hpp>
using HandleRange = boost::any_range<Handle, boost::forward_traversal_tag, const Handle>;
struct BasicCollection {
HandleRange GetPartHandles() const;
private:
Handle _collectionHandle;
};
HandleRange BasicCollection::GetPartHandles() const {
Handle h =
GenericHandleManager::CreatePartHandleValue(
GenericHandleManager::GetPartIdx(_collectionHandle));
return SingletonRange<Handle> {h};
}
#include <iostream>
int main() {
BasicCollection coll;
for (Handle h : coll.GetPartHandles()) {
std::cout << "Handle in loop\n";
boost::ignore_unused_variable_warning(h);
}
}
Keep in mind that copying that range is as expensive as copying an
iterator_range<Handle*> plus copying the Handle itself. I'm
assuming the Handle is lightweight (as usual for handles)
Prints
Handle in loop
¹ as long as you make sure you don't use any iterators from the SingletonRange after the lifetime of the range. This is a common C++ pattern though
Using gcc or clang latest, boost 1.68 (or 1.69),
Compiling boost.spirit.karma example customize_embedded_container.cpp fails, unless replacing type with value_type in line 26.
The other useful example, customize_use_as_container.cpp also fails, asking for value_type etc. in indirect_iterator,
" no named type 'value_type' in 'std::iterator_traits' "
For the reference, the example : https://www.boost.org/doc/libs/1_69_0/libs/spirit/example/karma/customize_use_as_container.cpp
Any that have a clue or a working example for container-specialisation that is compiling in boost.spirit.karma ?
Given my case, a skeleton for the solution, or rather a workaround just playing with the parts that really works easy in boost.spirit:
namespace X {
struct p { double t,v;};// point, time, value
struct ts { // simplified time-series representation, time-axis computed
bool s;
double t0,dt;size_t n;// ti = t0 + dt*i
std::vector<double> v;// v.size()===n
p point(size_t i ) const { return p{t0+dt*i,v[i]};}
};
//--would like to output grammar like {pfx:(true|false),data:[[t,v]..]}
//--; first construct a container class out of ts, using boost iterator_facade
//--; to get away with few lines.(simplified..)
struct ts_c {
using value_type=p;// iterate over (t,v), t is computed, v is plain vector
ts * c;
struct iterator:public::boost::iterator_facade<iterator,p,boost::random_access_traversal..> { //..
iterator(ts*c,size_t pos=0u):c{c},pos{pos} {}
//.. plain vanilla impl. goes here according to boost::iterator_facade.
private:
ts* c;
size_t pos;
};
using const_iterator=iterator;
iterator begin() const;//.. etc. impl. of need it stuff.
};
}
// use FUSION to adapt the ts-type, let last tuple member return the
// tuple members:
// 0 true if n>0, otherwise false
// 1 true if ts.s is true
// 2 returns a vanilla iterable container, ts_c exposing type p
BOOST_FUSION_ADAPT_ADT(
X::ts,
(bool,bool, obj.n>0,/**/)
(bool,bool,obj.s,/**/)
(X::ts_c,X::ts_c, X::ts_c(&obj),/**/)
)
//-- then combining the boost spirit complex example to emit the point class p
namespace X {
namespace ka=boost::spirit::karma;
/** generate a point like [123.0, 3.14], or [123.0,null] if !isfinite.
* using the complex example pattern given in boost::spirit,
*/
template<class OutputIterator>
struct point_generator:ka::grammar<OutputIterator,p()> {
point_generator():point_generator::base_type(pg) {
using ka::true_;
using ka::bool_;
using ka::omit;
pg =
&true_ <<( '[' << double_<< ',' << double_ << ']')
|
omit[bool_]<< ( '[' << double_<< ',' << "null" << ']')
;
}
ka::rule<OutputIterator,p()> pg;
};
/** #brief a ts generator
*
* outputs:
* {pfx:(true|false),data:[[t,v],..]}
* or if empty
* {pfx:null,data:null}
*/
template<class OutputIterator>
struct ts_generator:ka::grammar<OutputIterator,ts()> {
ts_generator():ts_generator::base_type(tsg) {
using ka::true_;
using ka::bool_;
using ka::omit;
tsg =
&true_ <<"{pfx:"<<bool_<<",data:"<<( '[' << pt_ % ',' << ']')<<'}'
|
omit[bool_]<< "{pfx:null: data:null}"
;
}
ka::rule<OutputIterator,ts()> tsg;
point_generator<OutputIterator> pt_;
};
}
EDIT: I think I have cracked it, here
(Non bijective here means we may have arguments of type const char or char* both mapping to const std::string&.)*
NOTE: I've been working at this and asking similar questions for a few days now. Nevertheless, I will present a summary from scratch, as it may make the question a decent resource.
I have a C function pointer:
R_c (*CFunc)( void* self, A1, A2, ..., Ak )
CFunc slot = nullptr;
And an associated C++ method:
class Base {
R_cxx f_cxx( X1, X2, ..., Xk );
}
I need to create a mechanism that forwards.
The C Library is going to invoke say x = slot(&someobject, 1, "two"), and my task is to create a slot function that will trampoline to:
slot( void* self, A1 a1, A2 a2 ) {
R_cxx ret = ((Base*)self)->f_cxx( toCxx<A1>(a1), toCXX<A2>(a2) );
return toC<R_cxx>(ret);
}
The problem is I have close to 100 different slots, spanning maybe 20 different signatures. So I need to automate this.
I would start with a template containing a static function:
template< typename F_c, typename F_Cxx >
struct Generator {
static Bla call( etc ) {...}
};
#define BIND_SLOT( F_c, F_Cxx ) &Generator<F_c,F_Cxx>::call
:
BIND_SLOT( table->slot35, Base::handler_35 );
Of course, that is semi-pseudocode. Actually the syntax is much more complicated, as you need to pass decltype(foofunc), foofunc into a template -- just foofunc alone is not sufficient (although there is some chance this will be fixed in C++17). Also an intermediate template layer is necessary for splitting a function signature into returntype, C++base and args. And a toCXX(T t) function would need to be overloaded to map all necessary A_k to X_k.
I thought I had this cracked yesterday thanks to this answer.
The solution was to construct the C function signature from f_cxx's signature. However I have since realised that this approach won't work for one annoying reason: Two different C-types map onto the same C++ type.
i.e. The slot-function may have a signature involving const char* and char*. But both of these get mapped onto 'const std::string&'. So that technique would fail the moment it comes across 'const std::string&' --it doesn't know whether to convert back to char* or const char*.
Hence I'm attempting to rewrite it, this time using the signature of the slot function, instead of the cxx member function.
However, this is extremely complex code, and I'm struggling.
The address of the slot is not a valid template parameter. I did not take the time to determine why, but in the code below I removed it from the parameter list. It was not being used in the example code.
Your first decltype has an extra Table. in it which makes the expression invalid. Removing this allows all the arguments to be seen. The expression became Table.table.tp_getattr before this was removed, which was invalid.
Your Return class was using the return type of the C function, but you specialized it on the return type of the C++ function.
Some of your helpers are doing things like returning a reference to a temporary or returning a pointer when a reference was expected. I cleaned those up somewhat as well, but note that it leaks memory.
Updated code (compiles on g++ 4.7.3):
#include <iostream>
#include <typeinfo>
#include <utility>
struct PyObject
{
PyObject(int i_) : i{i_} {}
int i;
};
struct Object
{
// avoid implicit conversion
explicit Object(PyObject* p_) : p{p_} {
std::cout << "Converting PyObject: " << p->i << std::endl;
}
PyObject* ptr() const {
return p;
}
private:
PyObject* p;
};
struct Table {
typedef PyObject* (*getattrfunc) (PyObject *, char * );
typedef PyObject* (*getattrofunc) (PyObject *, PyObject * );
typedef int (*setattrfunc) (PyObject *, char * , PyObject *);
typedef int (*setattrofunc) (PyObject *, PyObject * , PyObject *);
getattrfunc tp_getattr;
setattrfunc tp_setattr;
getattrofunc tp_getattro;
setattrofunc tp_setattro;
} table{};
class Base {
public:
Object getattr( const std::string& s ) { std::cout << "Base::getattr" << std::endl; return Object{ new PyObject(42) }; }
int setattr( const std::string& s, const Object& value ){ std::cout << "Base::setattr" << std::endl; return 666; }
};
class Final : public Base {
public:
Object getattr( const std::string& s ){ std::cout << "Final::getattr" << std::endl; return Object{ new PyObject(43) }; }
} final{};
// helpers
template<typename T, typename U> U&& mapperC2CXX( T&& t ) { return std::forward<U&&>(t); }
template<typename T> const std::string& mapperC2CXX( char* t ) { return *new std::string(t); }
template<typename T> const std::string& mapperC2CXX( const char* t ) { return *new std::string(t); }
template<typename T> const std::string& mapperC2CXX( PyObject* p ) { return *new Object{p}; }
template<typename T>
struct Return {
static T&& cvalue(T&& t) { return std::forward<T>(t); }
static T cerr() { return T(-1); }
};
template<>
struct Return<Object> {
static PyObject* cvalue(const Object& ob) { return ob.ptr(); }
static PyObject* cerr() { return (PyObject*)nullptr; }
};
// function generator
template<typename Fc, typename Target, Target target>
struct Generate;
template < typename R , typename ...Arg ,
typename RTarg , typename ...TargArg , RTarg(Base::*target)(TargArg...) >
struct Generate< R(*)(PyObject*, Arg...) ,
RTarg(Base::*)(TargArg...) , target >
{
static Base* cxxbase_for(PyObject* pyob) {
return (Base*)&final; // cheat for now!
}
static R call( PyObject* self, Arg... carg)
{
try
{
RTarg r_cxx = (cxxbase_for(self)->*target) (mapperC2CXX<Arg>(carg)...);
return Return<RTarg>::cvalue(r_cxx);
}
catch (...)
{
std::cout << "CAUGHT" << std::endl;
return Return<R>::cerr();
}
}
};
#define BIND(c_slot, cxx_target) c_slot = & Generate< decltype(c_slot), decltype(&cxx_target), &cxx_target >::call;
int main()
{
BIND( table.tp_getattr, Base::getattr );
// test -- imagine C library fires this
PyObject* self = (PyObject*)&final;
PyObject* pyob = table.tp_getattr( self, (char*)"someattribute" );
std::cout << pyob->i << std::endl;
}
I am using a container to hold a list of pointers to anything:
struct Example {
std::vector<boost::any> elements;
}
To insert elements in this container, I had written a couple of helper functions (members of the struct Example):
void add_any(boost::any& a) {
elements.push_back(a);
}
template<typename T>
void add_to_list(T& a) {
boost::any bany = &a;
add_any(bany);
}
Now, I would like to insert elements only when they are not present in this container. To do this, I thought that I would only need to call search over elements with an appropriate comparator function. However, I do not know how to compare the boost::any instances.
My question:
Knowing that my boost::any instances always contain a pointer to something; is it possible to compare two boost::any values?
update
I thank you for your answers. I have also managed to do this in a probably unsafe way: using boost::unsafe_any_cast to obtain a void** and comparing the underlying pointer.
For the moment, this is working fine. I would, however, appreciate your comments: maybe this is a big mistake!
#include <boost/any.hpp>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
bool any_compare(const boost::any& a1, const boost::any& a2) {
cout << "compare " << *boost::unsafe_any_cast<void*>(&a1)
<< " with: " << *boost::unsafe_any_cast<void*>(&a2);
return (*boost::unsafe_any_cast<void*>(&a1)) ==
(*boost::unsafe_any_cast<void*>(&a2));
}
struct A {};
class Example {
public:
Example() : elements(0),
m_1(3.14),
m_2(42),
m_3("hello"),
m_4() {};
virtual ~Example() {};
void test_insert() {
add_to_list(m_1);
add_to_list(m_2);
add_to_list(m_3);
add_to_list(m_4);
add_to_list(m_1); // should not insert
add_to_list(m_2); // should not insert
add_to_list(m_3); // should not insert
add_to_list(m_4); // should not insert
};
template <typename T>
void add_to_list(T& a) {
boost::any bany = &a;
add_any(bany);
}
private:
vector<boost::any> elements;
double m_1;
int m_2;
string m_3;
A m_4;
void add_any(const boost::any& a) {
cout << "Trying to insert " << (*boost::unsafe_any_cast<void*>(&a)) << endl;
vector<boost::any>::const_iterator it;
for (it = elements.begin();
it != elements.end();
++it) {
if ( any_compare(a,*it) ) {
cout << " : not inserting, already in list" << endl;
return;
}
cout << endl;
}
cout << "Inserting " << (*boost::unsafe_any_cast<void*>(&a)) << endl;
elements.push_back(a);
};
};
int main(int argc, char *argv[]) {
Example ex;
ex.test_insert();
unsigned char c;
ex.add_to_list(c);
ex.add_to_list(c); // should not insert
return 0;
}
You cannot directly provide it, but you can actually use any as the underlying type... though for pointers it's pointless (ah!)
struct any {
std::type_info const& _info;
void* _address;
};
And a templated constructor:
template <typename T>
any::any(T* t):
_info(typeid(*t)),
_address(dynamic_cast<void*>(t))
{
}
This is, basically, boost::any.
Now we need to "augment" it with our comparison mechanism.
In order to do so, we'll "capture" the implementation of std::less.
typedef bool (*Comparer)(void*,void*);
template <typename T>
bool compare(void* lhs, void* rhs) const {
return std::less<T>()(*reinterpret_cast<T*>(lhs), *reinterpret_cast<T*>(rhs));
}
template <typename T>
Comparer make_comparer(T*) { return compare<T>; }
And augment the constructor of any.
struct any {
std::type_info const& _info;
void* _address;
Comparer _comparer;
};
template <typename T>
any::any(T* t):
_info(typeid(*t)),
_address(dynamic_cast<void*>(t)),
_comparer(make_comparer(t))
{
}
Then, we provided a specialization of less (or operator<)
bool operator<(any const& lhs, any const& rhs) {
if (lhs._info.before(rhs._info)) { return true; }
if (rhs._info.before(lhs._info)) { return false; }
return (*lhs._comparer)(lhs._address, rhs._address);
}
Note: encapsulation, etc... are left as an exercise to the reader
The only easy way to do this I can think of involves hardcoding support for the types that you're storing in the any instances, undermining much of the usefulness of any...
bool equal(const boost::any& lhs, const boost::any& rhs)
{
if (lhs.type() != rhs.type())
return false;
if (lhs.type() == typeid(std::string))
return any_cast<std::string>(lhs) == any_cast<std::string>(rhs);
if (lhs.type() == typeid(int))
return any_cast<int>(lhs) == any_cast<int>(rhs);
// ...
throw std::runtime_error("comparison of any unimplemented for type");
}
With C++11's type_index you could use a std::map or std::unordered_map keyed on std::type_index(some_boost_any_object.type()) - similar to what Alexandre suggests in his comment below.
If you can change type in container, there is Boost.TypeErasure. It provides easy way to customize any. For example I'm using such typedef for similar purpose:
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/operators.hpp>
using Foo = boost::type_erasure::any<
boost::mpl::vector<
boost::type_erasure::copy_constructible<>,
boost::type_erasure::equality_comparable<>,
boost::type_erasure::typeid_<>,
boost::type_erasure::relaxed
>
>;
Foo behaves exactly the same as boost::any, except that it can be compared for equality and use boost::type_erasure::any_cast instead of boost::any_cast.
There is no need to create new class. Try to use 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 (creates comparable_any).
Maybe this algorithm come in handy >
http://signmotion.blogspot.com/2011/12/boostany.html
Compare two any-values by type and content. Attempt convert string to number for equals.
I was searching for an implementation of extension methods in c++ and came upon this comp.std.c++ discussion which mentions that polymorphic_map can be used to associated methods with a class, but, the provided link seems to be dead. Does anyone know what that answer was referring to, or if there is another way to extend classes in a similar manner to extension methods (perhaps through some usage of mixins?).
I know the canonical C++ solution is to use free functions; this is more out of curiosity than anything else.
Different languages approach development in different ways. In particular C# and Java have a strong point of view with respect to OO that leads to everything is an object mindset (C# is a little more lax here). In that approach, extension methods provide a simple way of extending an existing object or interface to add new features.
There are no extension methods in C++, nor are they needed. When developing C++, forget the everything is an object paradigm --which, by the way, is false even in Java/C# [*]. A different mindset is taken in C++, there are objects, and the objects have operations that are inherently part of the object, but there are also other operations that form part of the interface and need not be part of the class. A must read by Herb Sutter is What's In a Class?, where the author defends (and I agree) that you can easily extend any given class with simple free functions.
As a particular simple example, the standard templated class basic_ostream has a few member methods to dump the contents of some primitive types, and then it is enhanced with (also templated) free functions that extend that functionality to other types by using the existing public interface. For example, std::cout << 1; is implemented as a member function, while std::cout << "Hi"; is a free function implemented in terms of other more basic members.
Extensibility in C++ is achieved by means of free functions, not by ways of adding new methods to existing objects.
[*] Everything is not an object.
In a given domain will contain a set of actual objects that can be modeled and operations that can be applied to them, in some cases those operations will be part of the object, but in some other cases they will not. In particular you will find utility classes in the languages that claim that everything is an object and those utility classes are nothing but a layer trying to hide the fact that those methods don't belong to any particular object.
Even some operations that are implemented as member functions are not really operations on the object. Consider addition for a Complex number class, how is sum (or +) more of an operation on the first argument than the second? Why a.sum(b); or b.sum(a), should it not be sum( a, b )?
Forcing the operations to be member methods actually produces weird effects --but we are just used to them: a.equals(b); and b.equals(a); might have completely different results even if the implementation of equals is fully symmetric. (Consider what happens when either a or b is a null pointer)
Boost Range Library's approach use operator|().
r | filtered(p);
I can write trim for string as follows in the same way, too.
#include <string>
namespace string_extension {
struct trim_t {
std::string operator()(const std::string& s) const
{
...
return s;
}
};
const trim_t trim = {};
std::string operator|(const std::string& s, trim_t f)
{
return f(s);
}
} // namespace string_extension
int main()
{
const std::string s = " abc ";
const std::string result = s | string_extension::trim;
}
This is the closest thing that I have ever seen to extension methods in C++. Personally i like the way it can be used, and possibly this it the closest we can get to extension methods in this language. But there are some disadvantages:
It may be complicated to implement
Operator precedence may be not that nice some times, this may cause surprises
A solution:
#include <iostream>
using namespace std;
class regular_class {
public:
void simple_method(void) const {
cout << "simple_method called." << endl;
}
};
class ext_method {
private:
// arguments of the extension method
int x_;
public:
// arguments get initialized here
ext_method(int x) : x_(x) {
}
// just a dummy overload to return a reference to itself
ext_method& operator-(void) {
return *this;
}
// extension method body is implemented here. The return type of this op. overload
// should be the return type of the extension method
friend const regular_class& operator<(const regular_class& obj, const ext_method& mthd) {
cout << "Extension method called with: " << mthd.x_ << " on " << &obj << endl;
return obj;
}
};
int main()
{
regular_class obj;
cout << "regular_class object at: " << &obj << endl;
obj.simple_method();
obj<-ext_method(3)<-ext_method(8);
return 0;
}
This is not my personal invention, recently a friend of mine mailed it to me, he said he got it from a university mailing list.
The short answer is that you cannot do that. The long answer is that you can simulate it, but be aware that you'll have to create a lot of code as workaround (actually, I don't think there is an elegant solution).
In the discussion, a very complex workaround is provided using operator- (which is a bad idea, in my opinion). I guess that the solution provided in the dead link was more o less similar (since it was based on operator|).
This is based in the capability of being able to do more or less the same thing as an extension method with operators. For example, if you want to overload the ostream's operator<< for your new class Foo, you could do:
class Foo {
friend ostream &operator<<(ostream &o, const Foo &foo);
// more things...
};
ostream &operator<<(ostream &o, const Foo &foo)
{
// write foo's info to o
}
As I said, this is the only similar mechanism availabe in C++ for extension methods. If you can naturally translate your function to an overloaded operator, then it is fine. The only other possibility is to artificially overload an operator that has nothing to do with your objective, but this is going to make you write very confusing code.
The most similar approach I can think of would mean to create an extension class and create your new methods there. Unfortunately, this means that you'll need to "adapt" your objects:
class stringext {
public:
stringext(std::string &s) : str( &s )
{}
string trim()
{ ...; return *str; }
private:
string * str;
};
And then, when you want to do that things:
void fie(string &str)
{
// ...
cout << stringext( str ).trim() << endl;
}
As said, this is not perfect, and I don't think that kind of perfect solution exists.
Sorry.
To elaborate more on #Akira answer, operator| can be used to extend existing classes with functions that take parameters too. Here an example that I'm using to extend Xerces XML library with find functionalities that can be easily concatenated:
#pragma once
#include <string>
#include <stdexcept>
#include <xercesc/dom/DOMElement.hpp>
#define _U16C // macro that converts string to char16_t array
XERCES_CPP_NAMESPACE_BEGIN
struct FindFirst
{
FindFirst(const std::string& name);
DOMElement * operator()(const DOMElement &el) const;
DOMElement * operator()(const DOMElement *el) const;
private:
std::string m_name;
};
struct FindFirstExisting
{
FindFirstExisting(const std::string& name);
DOMElement & operator()(const DOMElement &el) const;
private:
std::string m_name;
};
inline DOMElement & operator|(const DOMElement &el, const FindFirstExisting &f)
{
return f(el);
}
inline DOMElement * operator|(const DOMElement &el, const FindFirst &f)
{
return f(el);
}
inline DOMElement * operator|(const DOMElement *el, const FindFirst &f)
{
return f(el);
}
inline FindFirst::FindFirst(const std::string & name)
: m_name(name)
{
}
inline DOMElement * FindFirst::operator()(const DOMElement &el) const
{
auto list = el.getElementsByTagName(_U16C(m_name));
if (list->getLength() == 0)
return nullptr;
return static_cast<DOMElement *>(list->item(0));
}
inline DOMElement * FindFirst::operator()(const DOMElement *el) const
{
if (el == nullptr)
return nullptr;
auto list = el->getElementsByTagName(_U16C(m_name));
if (list->getLength() == 0)
return nullptr;
return static_cast<DOMElement *>(list->item(0));
}
inline FindFirstExisting::FindFirstExisting(const std::string & name)
: m_name(name)
{
}
inline DOMElement & FindFirstExisting::operator()(const DOMElement & el) const
{
auto list = el.getElementsByTagName(_U16C(m_name));
if (list->getLength() == 0)
throw runtime_error(string("Missing element with name ") + m_name);
return static_cast<DOMElement &>(*list->item(0));
}
XERCES_CPP_NAMESPACE_END
It can be used this way:
auto packetRate = *elementRoot | FindFirst("Header") | FindFirst("PacketRate");
auto &decrypted = *elementRoot | FindFirstExisting("Header") | FindFirstExisting("Decrypted");
You can enable kinda extension methods for your own class/struct or for some specific type in some scope. See rough solution below.
class Extensible
{
public:
template<class TRes, class T, class... Args>
std::function<TRes(Args...)> operator|
(std::function<TRes(T&, Args...)>& extension)
{
return [this, &extension](Args... args) -> TRes
{
return extension(*static_cast<T*>(this), std::forward<Args>(args)...);
};
}
};
Then inherit your class from this and use like
class SomeExtensible : public Extensible { /*...*/ };
std::function<int(SomeExtensible&, int)> fn;
SomeExtensible se;
int i = (se | fn)(4);
Or you can declare this operator in cpp file or namespace.
//for std::string, for example
template<class TRes, class... Args>
std::function<TRes(Args...)> operator|
(std::string& s, std::function<TRes(std::string&, Args...)>& extension)
{
return [&s, &extension](Args... args) -> TRes
{
return extension(s, std::forward<Args>(args)...);
};
}
std::string s = "newStr";
std::function<std::string(std::string&)> init = [](std::string& s) {
return s = "initialized";
};
(s | init)();
Or even wrap it in macro (I know, it's generally bad idea, nevertheless you can):
#define ENABLE_EXTENSIONS_FOR(x) \
template<class TRes, class... Args> \
std::function<TRes(Args...)> operator| (x s, std::function<TRes(x, Args...)>& extension) \
{ \
return [&s, &extension](Args... args) -> TRes \
{ \
return extension(s, std::forward<Args>(args)...); \
}; \
}
ENABLE_EXTENSIONS_FOR(std::vector<int>&);
This syntactic sugar isn't available in C++, but you can define your own namespace and write pure static classes, using const references as the first parameter.
For example, I was struggling using the STL implementation for some array operations, and I didn't like the syntaxis, I was used to JavaScript's functional way of how array methods worked.
So, I made my own namespace wh with the class vector in it, since that's the class I was expecting to use these methods, and this is the result:
//#ifndef __WH_HPP
//#define __WH_HPP
#include <vector>
#include <functional>
#include <algorithm>
namespace wh{
template<typename T>
class vector{
public:
static T reduce(const std::vector<T> &array, const T &accumulatorInitiator, const std::function<T(T,T)> &functor){
T accumulator = accumulatorInitiator;
for(auto &element: array) accumulator = functor(element, accumulator);
return accumulator;
}
static T reduce(const std::vector<T> &array, const T &accumulatorInitiator){
return wh::vector<T>::reduce(array, accumulatorInitiator, [](T element, T acc){return element + acc;});
}
static std::vector<T> map(const std::vector<T> &array, const std::function<T(T)> &functor){
std::vector<T> ret;
transform(array.begin(), array.end(), std::back_inserter(ret), functor);
return ret;
}
static std::vector<T> filter(const std::vector<T> &array, const std::function<bool(T)> &functor){
std::vector<T> ret;
copy_if(array.begin(), array.end(), std::back_inserter(ret), functor);
return ret;
}
static bool all(const std::vector<T> &array, const std::function<bool(T)> &functor){
return all_of(array.begin(), array.end(), functor);
}
static bool any(const std::vector<T> &array, const std::function<bool(T)> &functor){
return any_of(array.begin(), array.end(), functor);
}
};
}
//#undef __WH_HPP
I wouldn't inherit nor compose a class with it, since I've never been able to do it peacefully without any side-effects, but I came up with this, just const references.
The problem of course, is the extremely verbose code you have to make in order to use these static methods:
int main()
{
vector<int> numbers = {1,2,3,4,5,6};
numbers = wh::vector<int>::filter(numbers, [](int number){return number < 3;});
numbers = wh::vector<int>::map(numbers,[](int number){return number + 3;});
for(const auto& number: numbers) cout << number << endl;
return 0;
}
If only there was syntactic sugar that could make my static methods have some kind of more common syntax like:
myvector.map([](int number){return number+2;}); //...