find_if on vector<Message*> with bind2nd and functor - c++

I have a vector like this :
typedef vector<Message*> OmciMessages;
OmciMessages omciResponses;
And I have a functor like following which I suspect is not correct :
class isMatching{
public:
bool operator()(const Message* responseMsg,unsigned short transactionid){
return responseMsg->getTransactionId()==transactionid;
}
};
then I call find_if and want to use the functor to find something in the vector but only for a specific transactionid that is inside my class :
OmciMessages::iterator responseit
= find_if(omciResponses.begin(),
omciResponses.end(),
bind2nd(isMatching(),transactionid));
The compiler does not like it and spawns quite a lot of error messages that are hard to interpret typically for template classes.
/repo/stuyckp/ngpon2WW/tools/cm4/tools/GNU/src/gcc/i686-pc-linux-gnu/bin/../lib/gcc/i686-pc-linux-gnu/3.4.6/../../../../../include/c++/3.4.6/bits/stl_function.h:429: error: no type named `first_argument_type' in `class isMatching'
It worked if I did it like this without a function object :
static bool isMatching(Message* responseMsg){
return responseMsg->getTransactionId()==transactionid;
}
transactionid = 5; //global variable being used. yuck, don't like it
find_if(omciResponses.begin(),
omciResponses.end(),
isMatching);
but then I needed a global variable transaction id that was set beforehand which I think is not that good a design.
So how is this supposed to be done with the bind2nd approach ?

Given the version of your compiler, I assume that C++11 is not an option (otherwise the answer is simple: use a lambda).
The old function object binders (deprecated in C++11, removed in C++17) require a bunch of nested typedefs. You need to define result_type, first_argument_type, and second_argument_type as members of isMatching, either directly or via the binary_function helper (which is also deprecated in C++11 and removed in C++17), to use it with bind2nd.
You can also use a plain function taking two arguments, adapt it with ptr_fun (again, deprecated in C++11 and removed in C++17), and then bind with bind2nd.
Or just use a stateful functor, as shown in Piotr's answer.

bind2nd needs your functor class to be adaptable, i.e. provide certain typedefs, including first_argument_type, second_argument_type, and result_type. You can define them by yourself in the functor classes, or inherit from std::binary_function to make it easy:
class isMatching : public std::binary_function<const Message*, unsigned short, bool> {
public:
bool operator()(const Message* responseMsg, unsigned short transactionid) const {
return responseMsg->getTransactionId() == transactionid;
}
};

struct isMatching
{
unsigned short transactionid;
explicit isMatching(unsigned short transactionid) : transactionid(transactionid) {}
bool operator()(const Message* responseMsg) const
{
return responseMsg->getTransactionId() == transactionid;
}
};
std::find_if(omciResponses.begin()
, omciResponses.end()
, isMatching(0));
// ^ transactionId to be searched for
DEMO
Note that if you urge to use std::bind2nd, or the function object would be stateless, then you don't need a function object as a separate class at all:
bool isMatching(const Message* responseMsg, unsigned short transactionid)
{
return responseMsg->getTransactionId() == transactionid;
}
std::find_if(omciResponses.begin()
, omciResponses.end()
, std::bind2nd(std::ptr_fun(&isMatching), 0));
// ~~~~~~~~~~~^ ^ transactionId to be searched for
// transform to a function object
DEMO 2

Related

C++ constructor with optional parameters

Hi I am new to C++ and I am trying to create a class hierarchy where each class represents a node in a schema document, think json-schema. Have a look at the representation of e.g. a string. A string can have three optional constraints
min_length
max_length
pattern
Furthermore a string is a type so it would make sense to have a base class representing a type from which all types (boolean, number, ...) inherit. Now, one way to achieve this is by writing something like
struct Type {
const std::string m_name;
Type(const std::string& name)
: m_name{name}
{}
virtual X Serialize() const {
//...
}
};
struct String : Type {
const int m_max_len;
const int m_min_len;
const std::string m_pattern;
String(int min_len, int max_len, const std::string& pattern)
: Type("string")
, m_min_len(min_len)
, m_max_len(max_len)
, m_pattern(pattern)
{}
X Serialize() const override {
// If min_length was not set then it should be omitted from the serialized output.
}
};
This String implementation would not make the constraints optional. What to do?
Options:
One could employ a strategy where the default constructor parameters where set to some "illegal" value like INT_MIN (which would work in this case because the length can not be negative) but that would not work in the general case. It could very well be that all possible integers a legal values, the same goes for the pattern parameter.
You do not want to have different constructors for every possible permutation of optional parameters. In this case there are three optional values which would yield 2^3 different constructors. Also it would not be possible for the compiler to distinguish between the constructors String(int min_length) and String(int max_length).
It would be possible to do something like
String(int* min_length = nullptr, int* max_length = nullptr, const std::string* nullptr)
but then you would have to use new/delete or give lvalues for the set parameters.
Finally each member could be a std::unique_ptr.
String(std::unique_ptr<int> min_value nullptr, std::unique_ptr<int> max_value = nullptr, std::unique_ptr<const std::string> pattern = nullptr)
but then you would end up with quite complicated calls when creating an instance of String. Also if implementing a container of Types which may have optional parameters of its own things quickly get out of hand.
Finally, the code must be compatible with C++14.
You can simply use std::optional:
String(const std::optional<int> &min_len, const std::optional<int> &max_len,
const std::optional<std::string> &pattern);
Type *type = new String(5, {}, std::nullptr); // last 2 parameters are omitted.
For C++14 you can use similar constructs that exist in other open source libraries, (e.g. boost::optional, folly::Optional).
I lack reputation points to comment on #Kostas
To be compatible with C++14 you can try experimental namespace which has optional (if it is available/works on your compiler)
#include <experimental/optional>
then you can use
String(std::experimental::optional<int> &min_len,.....)
min_len.value_or(-1)
You can write your own class that can contain value or not if you can't use std::optional. It is not like lot of code. Can make its interface like std::optioal has or can make something different, what matters is data:
class OptInt {
bool set_;
int value_;
public:
OptInt() : set_(false) , value_(0) {}
OptInt(int v) : set_(true), value_(v) {}
// can add other ways how to create it
bool isSet() const {return set_;}
int get() const {if (!set_) throw 666; return value_;}
// can add other operations you want to it.
};
Then you can use such default-constructed OptInt as your default argument and so it will be not set, but if caller provides int argument then it will be set.
Have you tried to use an std::optional (since C++17)?
I know you mentioned the need to use C++14 compatible code, but there is a boost::optional available.

std::any without RTTI, how does it work?

If I want to use std::any I can use it with RTTI switched off. The following example compiles and runs as expected also with -fno-rtti with gcc.
int main()
{
std::any x;
x=9.9;
std::cout << std::any_cast<double>(x) << std::endl;
}
But how std::any stores the type information? As I see, if I call std::any_cast with the "wrong" type I got std::bad_any_cast exception as expected.
How is that realized or is this maybe only a gcc feature?
I found that boost::any did also not need RTTI, but I found also not how that is solved. Does boost::any need RTTI?.
Digging into the STL header itself gives me no answer. That code is nearly unreadable to me.
TL;DR; std::any holds a pointer to a static member function of a templated class. This function can perform many operations and is specific to a given type since the actual instance of the function depends on the template arguments of the class.
The implementation of std::any in libstdc++ is not that complex, you can have a look at it:
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/any
Basically, std::any holds two things:
A pointer to a (dynamically) allocated storage;
A pointer to a "storage manager function":
void (*_M_manager)(_Op, const any*, _Arg*);
When you construct or assign a new std::any with an object of type T, _M_manager points to a function specific to the type T (which is actually a static member function of class specific to T):
template <typename _ValueType,
typename _Tp = _Decay<_ValueType>,
typename _Mgr = _Manager<_Tp>, // <-- Class specific to T.
__any_constructible_t<_Tp, _ValueType&&> = true,
enable_if_t<!__is_in_place_type<_Tp>::value, bool> = true>
any(_ValueType&& __value)
: _M_manager(&_Mgr::_S_manage) { /* ... */ }
Since this function is specific to a given type, you don't need RTTI to perform the operations required by std::any.
Furthermore, it is easy to check that you are casting to the right type within std::any_cast. Here is the core of the gcc implementation of std::any_cast:
template<typename _Tp>
void* __any_caster(const any* __any) {
if constexpr (is_copy_constructible_v<decay_t<_Tp>>) {
if (__any->_M_manager == &any::_Manager<decay_t<_Tp>>::_S_manage) {
any::_Arg __arg;
__any->_M_manager(any::_Op_access, __any, &__arg);
return __arg._M_obj;
}
}
return nullptr;
}
You can see that it is simply an equality check between the stored function inside the object you are trying to cast (_any->_M_manager) and the manager function of the type you want to cast to (&any::_Manager<decay_t<_Tp>>::_S_manage).
The class _Manager<_Tp> is actually an alias to either _Manager_internal<_Tp> or _Manager_external<_Tp> depending on _Tp.
This class is also used for allocation / construction of object for the std::any class.
Manual implementation of a limited RTTI is not that hard. You're gonna need static generic functions. That much I can say without providing a complete implementation.
here is one possibility:
class meta{
static auto id(){
static std::atomic<std::size_t> nextid{};
return ++nextid;//globally unique
};
std::size_t mid=0;//per instance type id
public:
template<typename T>
meta(T&&){
static const std::size_t tid{id()};//classwide unique
mid=tid;
};
meta(meta const&)=default;
meta(meta&&)=default;
meta():mid{}{};
template<typename T>
auto is_a(T&& obj){return mid==meta{obj}.mid;};
};
This is my first observation; far from ideal, missing many details. One may use one instance of meta as a none-static data member of his supposed implementation of std::any.
One of possible solutions is generating unique id for every type possibly stored in any (I assume You know moreless how any internally works). The code that can do it may look something like this:
struct id_gen{
static int &i(){
static int i = 0;
return i;
}
template<class T>
struct gen{
static int id() {
static int id = i()++;
return id;
}
};
};
With this implemented You can use the id of the type instead of RTTI typeinfo to quickly check the type.
Notice the usage of static variables inside functions and static functions. This is done to avoid the problem of undefined order of static variable initialization.

Implementing an any container

I'm well aware of boost::any and boost::variant, but in this instance they don't fit my needs.
Normally, to contain an object of unknown type, one would derive it from a common base and access the instance through virtual methods. But, what can one do if it's impossible to use a common base?
I know that in this example you would have to know the contained type, but bear with me. std::vector is a template class with top level class also being a template. As far as I know it cannot be given a non-template base without modifying the STL headers. Now, lets say I want to create a vector of a single type but the containing class doesn't care about the type, but it does require access to some of the 'common' methods, size() and pop_back() for example.
Using boost::any, the type has been erased, making it almost impossible to dereference the contained object. boost::variant and tuple require knowing before hand what types may be inserted, causing the containing class to itself be a template.
What I have so far is something like this:
struct container
{
virtual ~container() = 0;
virtual void pop_back() = 0;
virtual size_t size() = 0;
...
}
template < typename T >
struct contained
{
std::vector< T > _vec;
contained ( size_t n, T _what ) : _vec( n, _what ) {}
virtual void pop_back() { _vec.pop_back(); }
...
}
class some_class
{
container* _cont;
template < typename T >
void create ( T _first ) { _cont = new contained< T >(1,_first); }
...
}
Here the client can call on create() and the template parameter should be determined automatically. Not a great example I know, but I'm trying to hide the template parameters from the client. Without doing this, some_class would have to also keep track of what type is being stored.
My method relies on virtual calls which causes a performance loss, especially when the internal class has virtual methods of it's own.
Are there any other types of containers that would better suit my needs?
Ideally, I'd like something like this
container = std::vector< T >;
container.pop_back();
container.push_back( T2 ); // compile error if types don't match
Where internally it would track the type and do a simple cast rather than rely on virtual methods. Almost like auto with the difference being that once declared it's type can change.
Edit:
In reality, I want to create a wrapper around std::basic_filebuf. This wrapper class opens the file with char,wchar_t or unsigned long based on the BOM. The wrapper is also derived from basic_filebuf with the template parameter being whatever the client chooses. Internally, it converts unicode code points from the file to the clients desired encoding. The problem arises when storing the internal basic_filebuf because it can be declared with any type as the template parameter. I don't want to use template specialization because I want the client to be able to pass in their own basic_filebuf instance.
Must be VS2010 compatible, which has limited features from C++11.
This cannot be combined with compile-time type checking. Based on your "ideally" example:
container c;
if (thingKnownAtRunTime()) {
c = vector<int>;
} else {
c = vector<string>;
}
c.push_back("hello world");
For the filebuf case, though, you might get good enough with something like (warning: untested)
template<typename FILEBUF>
void gensputc(FILEBUF* fb, long long c) {
FILEBUf::char_type c2 = smart_convert<FILEBUf::char_type>(c);
fb->sputc(c2);
}
class FileBufWrapper {
public:
template<typename FILEBUF> FileBufWrapper(FILEBUF* fb) {
fb_ = fb;
sputc_ = gensputc<FILEBUF>;
}
void sputc(long long c) {
sputc_(fb_,c);
}
private:
typedef void(*sputc_t)(void*, long long);
sputc_t sputc_;
void* fb_;
};
The smart_convert function throws a runtime exception if the value cannot be converted to the char type. Also, this needs to be done for every function you intend to call.
If you have access to c++11's std::function and std::bind, this can be made a little cleaner, especially for the cases where you don't need to convert anything.

c++ sort class with class vector inside

I have a class cl1:
class c1
{
long double * coords;
...
}
I also have a second class cl2:
class cl2
{
vector<cl1*> cl1_vec;
unsigned int d;
...
}
I would like to sort cl1_vec, from cl2, based on coords[d], using the sort function for vectors.
So i could have something like
sort(cl2_inst->cl1_vec.begin(),cl2_inst->cl1_vec.end(), ??? );
I tried approches like
sort the 'std::vector' containing classes
C++ std::sort with predicate function in Class
but i couldn't make my way to solving this.
Thanks for any help that comes this way.
The code i've tried:
class cl1 {
public:
long double* coords;
cl1(long double *, unsigned int);
cl1();
cl1(const cl1& orig);
virtual ~cl1();
};
class cl2 {
public:
unsigned int d;
vector<cl1*> cl1_vec;
//the srting functions
static bool compareMyDataPredicate(cl1* lhs, cl1* rhs)
{
return (lhs->coords[d] < rhs->coords[d]);
};
// declare the functor nested within MyData.
struct compareMyDataFunctor : public binary_function<my_point*, my_point*, bool>
{
bool operator()( cl1* lhs, cl1* rhs)
{
return (lhs->coords[d] < rhs->coords[d]);
}
};
...
...
}
then in main
std::sort(cl2_inst->cl1_vec.begin(),cl2_inst->cl1_vec.end(),cl2::compareMyDataPredicate() );
The error is because you are accessing a non-static member d from a static context of the comparator function. Use the second approach, in the following way:
Provide a constructor to that struct, which takes a parameter unsigned int and sets a member to that value.
Create an object of type compareMyDataFunctor, and pass in the value of d to the constructor.
Use this object for sorting (3rd argument to std::sort)
I am not sure about the problems, because you were not precise enough about what exactly "does not work" means in your case (does not compile, does compile but does not sort etc). In case it does not compile (most likely guess) you did not post the error messages, which also makes finding and explaining the problem very hard.
Here are some guesses based on the code you posted:
Both static function as well as the functor use the member d to decide which column to sort on. However d is an instance variable, so it is not available for anything which is static. Neither the functor nor the static member function would know which of the possible ds to use, as there is one d per instance.
The best way to do this without resorting to C++11 features (lamdas) is to provide a constructor to the functor which takes the d you are planning to use. Something like this:
struct compareMyDataFunctor : public binary_function<cl1*, cl1*, bool>
{
compareMyDataFunctor( unsigned int d ) : d( d ) {}
bool operator()( cl1* lhs, cl1* rhs)
{
return (lhs->coords[d] < rhs->coords[d]);
}
unsigned int d;
};
This should do the trick.
There are some more things wrong with the code you posted though:
Arrays should be indexed using type size_t not a unsigned int. Same goes for std::vectors
The types in the std::binary_function instantiation do not match the actual types in the method (may be a problem of reducing the code).
Do not use using namespace std (I assume you do from the declarations in your code).
Functors such as these should take parameters as const-reference, not by value.
That's all I can think of. Next time try to present short, self contained, complete examples, then people will not have to resort to guessing.

mem_func and virtual function

I have the following classes:
class A
{
public:
virtual void myfunc(unsigned char c, std::string* dest) = 0;
};
class B : public class A
{
public:
virtual void myfunc(unsigned char c, std::string* dest);
};
void someOtherFunc(const std::string& str,A *pointerFunc)
{
std::string tmp;
for_each(str.begin(),
str.end(),
std::bind2nd(std::mem_fun(pointerFunc->myfunc), &tmp));
}
I get the following compilation error:
error: no matching function for call to \u2018mem_fun()\u2019
Do you know why?
You're looking for std::mem_fun(&A::myfunc).
EDIT: You can't use mem_fun at all here -- no overload of mem_fun allows you to make a two argument member function into a functor. You're going to have to use something like boost::bind/std::tr1::bind (If you have TR1)/std::bind (If you have C++0x) or you're going to have to write your own functor.
Note that even if mem_fun was able to do this sort of binding, then std::bind2nd would fail, because bind2nd expects a functor taking two arguments, and binding a member function pointer like this is going to produce a functor with three arguments.
You have a few ways around this:
Write your own functor that does what you want.
Write an explicit loop instead of std::for_each.
One of the not-yet-standard binder functions I mentioned above (and demonstrated in #David's answer)
Don't bother with the virtual function in the first place -- make your method accept a plain function pointer and implement things in terms of the function pointer. Of course this only works if myfunc doesn't depend on members of the class to which it belongs (in which case it shouldn't have ever been put into a class in the first place)
What you are trying to use here is use a pointer to a member function to apply a member function of another object to every object in the container. Apparently none of the adapters will work in this case. In that case the only solution is to write a special wrapper functor class for it.
Looking at the implementation behind of std::mem_fun you should be able to write your own:
EDIT (made it "human-readable")
template<class Result, class Ty, class Arg>
class mem_fun1_t : public binary_function<Ty*, Arg, Result>
{
private:
Result (Ty::*m_mf)(Arg);
public:
mem_fun1_t(Result (Ty::*mf)(Arg)) : m_mf(mf) { }
Result operator()(Ty* pLeft, Arg Right) const {
return ((pLleft->*m_mf)(Right));
}
};
Your declaration does not represent what you want to do.
try:
void someOtherFunc(const std::string& str)
{
std::string tmp;
B BInstance;
A* ptrToB = &BInstance;
for_each(str.begin(),
str.end(),
boost::bind(&A::myfunc, ptrToB, _1, &tmp));
}
this (or a variation of) should do what you want.