Constructor can't take non const reference - c++

I have the following class:
class Foo
{
public:
explicit Foo(std::vector<std::string>& functionCalls)
{
}
};
typedef boost::shared_ptr<Foo> FooPtr;
Which I try to use like this:
std::vector<std::string> functionCalls;
FooPtr foo = boost::make_shared<Foo>(functionCalls);
I compiles fine in VS20012 but it wont compile in gcc 4.3.4.
Here's the compiler error:
boost/boost_1_54_0/boost/smart_ptr/make_shared_object.hpp: In function 'typename boost::detail::sp_if_not_array<T>::type boost::make_shared(const A1&) [with T = Foo, A1 = std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >]':
main.cc:39: instantiated from here
boost/boost_1_54_0/boost/smart_ptr/make_shared_object.hpp:711: error: no matching function for call to 'Foo::Foo(const std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&)'
Foo.h:23: note: candidates are: Foo::Foo(std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&)
Foo.h:21: note: Foo::Foo(const Foo&)
If I change the construct of Foo to take a const then it compiles fine. However, I need to pass by reference. What do you think this issue is?

As documented here, without C++11 support make_shared can only take its arguments by const reference.
With C++11 support, it can take any reference types, and forward them to the constructor. Presumably that's what VS is doing.
As mentioned in the documentation, you can pass a non-const reference by wrapping it in boost::ref:
FooPtr foo = boost::make_shared<Foo>(boost::ref(functionCalls));

Related

boost::bind and insert of a boost::unordered_map

I want to use boost::bind to create a boost::function inserting a new key-value pair into a boost::unoredered_map but I got few compilation errors.
typedef boost::unordered_map<
std::string, std::string > dict_type;
inline void insert( const std::string& key, const std::string& value ){
typedef std::pair<dict_type::iterator, bool> out_type;
dict_type::value_type to_insert(key,value);
boost::function<void()> f = boost::bind<out_type>(
&dict_type::insert
,obj_
,boost::cref(to_insert)
);
}
The error below looks like bind cannot find the right overload for unordered_map::insert. In this case I specify exactly the right overload but this time it doesn't work. Do you know what it is?
../include2/llve_clorder_id.h:32: error: no matching function for call to
'bind(<unresolved overloaded function type>,
boost::unordered_map<std::basic_string<char, std::char_traits<char>,
std::allocator<char> >, std::basic_string<char, std::char_traits<char>,
std::allocator<char> >, boost::hash<std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, std::equal_to<std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, std::allocator<std::pair<const std::basic_string<char,
std::char_traits<char>, std::allocator<char> >, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > > > >&, const
boost::reference_wrapper<const std::pair<const std::basic_string<char,
std::char_traits<char>, std::allocator<char> >, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > > >)'
The problem is that boost::unordered_map contains more than one insert, so &dict_type::insert is ambiguous. The simplest solution is to define a function to call the correct overload:
void insert(dict_type & dict, dict_type::value_type const & value) {
dict.insert(value);
}
boost::function<void()> f = boost::bind(
insert
,boost::ref(obj_)
,boost::cref(to_insert)
);
or you could specify the overload explicitly:
boost::function<void()> f = boost::bind(
static_cast<out_type (dict_type::*)(dict_type::value_type const &)>(&dict_type::insert)
,obj_
,boost::cref(to_insert)
);
In C++11, you can avoid the problem with a lambda:
std::function<void()> f = [&](){obj_.insert(to_insert);};
http://www.boost.org/doc/libs/1_49_0/libs/bind/bind.html#Troubleshooting suggests that you can sometimes work around problems with overloaded functions by casting the pointer-to-member-function to the desired type. Using a temporary variable to stop it becoming completely unreadable, it would look like:
typedef std::pair<typename dict_type::iterator, bool> out_type;
typename dict_type::value_type to_insert(key,value);
out_type (dict_type::*ins) (typename dict_type::value_type const&) const = &dict_type::insert;
boost::function<void()> f = boost::bind(
ins
,obj_
,boost::cref(to_insert)
);

How to link STL in c++ code?

I wrote some code in source file sql_parse.cc of MySql 5.5.7rc. There I have used vector, allocator, etc but the compiler is not being linked with Standard Template Library(STL). Can anybody suggest me what should I do?
Here is the error msg :
libsql.a(sql_parse.cc.o): In function `std::vector<std::basic_string<char,
std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char,
std::char_traits<char>, std::allocator<char> > > >::push_back(std::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&)':
sql_parse.cc:(.text._ZNSt6vectorISsSaISsEE9push_backERKSs[std::vector<std::basic_string<char,
std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char,
std::char_traits<char>, std::allocator<char> > > >::push_back(std::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&)]+0x74): undefined reference to
`std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >
>::_M_insert_aux(__gnu_cxx::__normal_iterator<std::basic_string<char,
std::char_traits<char>, std::allocator<char> >*, std::vector<std::basic_string<char,
std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char,
std::char_traits<char>, std::allocator<char> > > > >, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&)'
collect2: ld returned 1 exit status
You should've given the command line. I suspect that you use gcc for linking in which case you should either use g++ or add -lstdc++ option.
I got my stl code to compile with the following
g++ -std=c++11 file.cpp -o prog
undefined reference to
std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >
::_M_insert_aux(__gnu_cxx::__normal_iterator<std::basic_string<char,
std::char_traits<char>, std::allocator<char> >*, std::vector<std::basic_string<char,
std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char,
std::char_traits<char>, std::allocator<char> > > > >, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&)'
That symbol is a member function of std::vector<std::string> and is a function template, so should be instantiated in your program, not in the C++ standard library.
Are you compiling with the -fno-implicit-templates option? Or using an explicit instantiation declaration (i.e. extern template) in your code and not providing the definition? Those would prevent the compiler from instantiation the template.
If you're telling the compiler not to provide implicit instantiations then you will need to add an explicit instantiation for each undefined reference:
template void std::vector<std::string>::_M_insert_aux(std::vector<std::string>::iterator, std::string const&);
#ifndef GLOBAL_H
#define GLOBAL_H
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
#endif //GLOBAL_H
Is a good start

error: '__pred' cannot be used as a function

I can't find what I'm doing wrong here. The function eta does what I ask but when I use it in the loop I get the attached error.
bool eta(map<string, TLorentzVector> map_jets, string jet){
return( fabs(map_jets[jet].PseudoRapidity()) > 2.5 );
}
and then
vector<pair<string,double> > jets_pt( vec_jets.size() );
for( vector<pair<string,double> >::iterator it = jets_pt.begin(); it != jets_pt.end(); ++it)
jets_pt.erase(remove_if(jets_pt.begin(),jets_pt.end(),eta(map_jets,it1->first)),jets_pt.end);
I get the error
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h: In function '_OutputIterator std::remove_copy_if(_InputIterator, _InputIterator, _OutputIterator, _Predicate) [with _InputIterator = __gnu_cxx::__normal_iterator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>*, std::vector<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double> > > >, _OutputIterator = __gnu_cxx::__normal_iterator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>*, std::vector<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double> > > >, _Predicate = bool]':
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:1291: instantiated from '_ForwardIterator std::remove_if(_ForwardIterator, _ForwardIterator, _Predicate) [with _ForwardIterator = __gnu_cxx::__normal_iterator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>*, std::vector<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double> > > >, _Predicate = bool]'
/misc/cdf/gbertoli/hww/Diboson_v20_taus/Ana/src/Functions.cc:25: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:1216: error: '__pred' cannot be used as a function
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h: In function '_RandomAccessIterator std::__find_if(_RandomAccessIterator, _RandomAccessIterator, _Predicate, std::random_access_iterator_tag) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>*, std::vector<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double> > > >, _Predicate = bool]':
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:338: instantiated from '_InputIterator std::find_if(_InputIterator, _InputIterator, _Predicate) [with _InputIterator = __gnu_cxx::__normal_iterator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>*, std::vector<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double> > > >, _Predicate = bool]'
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:1287: instantiated from '_ForwardIterator std::remove_if(_ForwardIterator, _ForwardIterator, _Predicate) [with _ForwardIterator = __gnu_cxx::__normal_iterator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>*, std::vector<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, double> > > >, _Predicate = bool]'
/misc/cdf/gbertoli/hww/Diboson_v20_taus/Ana/src/Functions.cc:25: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:260: error: '__pred' cannot be used as a function
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:264: error: '__pred' cannot be used as a function
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:268: error: '__pred' cannot be used as a function
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:272: error: '__pred' cannot be used as a function
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:280: error: '__pred' cannot be used as a function
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:284: error: '__pred' cannot be used as a function
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:288: error: '__pred' cannot be used as a function
mv: cannot stat `/misc/cdf/gbertoli/hww/Diboson_v20_taus/tmp/Linux2.6-GCC_4_1/Ana/srt_dep_tmp.27294': No such file or directory
gmake[2]: *** [/misc/cdf/gbertoli/hww/Diboson_v20_taus/tmp/Linux2.6-GCC_4_1/Ana/libAna-shared/Functions.o] Error 1
gmake[1]: *** [src.lib] Error 2
gmake: *** [Ana.all] Error 2
First off, the only valid signature for remove_if takes a single function as the predicate argument:
jets_pt.erase(std::remove_if(jets_pt.begin(), jets_pt.end(), eta),
jets_pt.end());
This means that eta must be a function returning bool and taking precisely one argument whose type is the value type of the container:
bool eta(const std::pair<string, double> & p)
{
// do something useful with p
}
If this doesn't fit your bill because you need additional state information in the predicate, then you need to make it a function object:
struct Eta
{
const std::map<string, TLorentzVector> & map_jets;
Eta(const std::map<string, TLorentzVector> & m) : map_jets(m) { }
bool operator()(const std::pair<string, double> & p) const
{
std::map<string, TLorentzVector>::const_iterator it = map_jets.find(p->second);
return it == map_jets.end() ?
false :
std::fabs(it->second.PseudoRapidity()) > 2.5;
}
};
Now you have to use remove_if with an instance of Eta:
jets_pt.erase(std::remove_if(jets_pt.begin(), jets_pt.end(), Eta(map_jets)),
jets_pt.end()); // ^^^^^^^^^^^^^
Note that your use of the for loop is extremely suspicious; you should double-check that.
std::remove_if takes a value of the contained type (bool pred (container::value_type), or a functor which overloads operator() appropriately).
For std::map, you have to do it like explained here remove_if equivalent for std::map .
You're passing a bool (the results of calling eta) to remove_if as
the third argument. You need to pass it a predicate: a pointer to a
function taking a single argument and returning something which can be
converted to a bool, or a functional object. In the error messages,
__pred is your third argument; remove_if calls it here with a
pair<string, double>, and expects a bool in return. You have to
provide something which can be called like this. (You might want to
look into boost::bind.)
And BTW: passing a map by value to eta might not be a good idea.
It's going to slow things down considerably if the map is big.

Using boost::lexical_cast with std::transform

g++ doesn't like:
vector<int> x;
x += 1,2,3,4,5;
vector<string> y(x.size());
transform(x.begin(), x.end(), y.begin(), lexical_cast<string>);
The error message is:
error: no matching function for call to 'transform(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, <unresolved overloaded function type>)'
Which clearly indicates there is an issue with lexical_cast as the last argument to transform... Is there a way to avoid writing a function object that wraps lexical_cast?
Thanks!
This is untested, but you could try:
transform(x.begin(), x.end(), y.begin(), lexical_cast<string, int>);
lexical_cast is a template with two template parameters. Normally the second one is deduced from type deduction from the argument, but you aren't providing an argument, so you need to explicitly specify it.

Shallow/deep copy of std::map

How would I best implement these? I thought of something like this:
using namespace std;
shape_container
shape_container::clone_deep () const
{
shape_container* ptr = new shape_container();
copy( data.begin(), data.end(), (*ptr).begin() );
return *ptr;
}
shape_container
shape_container::clone_shallow () const
{
return *( new shape_container(*this) );
}
The member data is defined as follows:
std::map<std::string, shape*> data;
This doesn't work, unfortunately. Here's the compiler errors, I don't really understand them:
g++ -Wall -O2 -pedantic -I../../UnitTest++/src/ -I./libfglwin/include/ -I. -c shape_container.cpp -o shape_container.o
/usr/include/c++/4.2.1/bits/stl_pair.h: In member function ‘std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>& std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>::operator=(const std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>&)’:
/usr/include/c++/4.2.1/bits/stl_pair.h:69: instantiated from ‘static _OI std::__copy<<anonymous>, <template-parameter-1-2> >::copy(_II, _II, _OI) [with _II = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, _OI = std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, bool <anonymous> = false, <template-parameter-1-2> = std::bidirectional_iterator_tag]’
/usr/include/c++/4.2.1/bits/stl_algobase.h:315: instantiated from ‘_OI std::__copy_aux(_II, _II, _OI) [with _II = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, _OI = std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >]’
/usr/include/c++/4.2.1/bits/stl_algobase.h:340: instantiated from ‘static _OI std::__copy_normal<<anonymous>, <anonymous> >::__copy_n(_II, _II, _OI) [with _II = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, _OI = std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, bool <anonymous> = false, bool <anonymous> = false]’
/usr/include/c++/4.2.1/bits/stl_algobase.h:401: instantiated from ‘_OutputIterator std::copy(_InputIterator, _InputIterator, _OutputIterator) [with _InputIterator = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, _OutputIterator = std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >]’
shape_container.cpp:70: instantiated from here
/usr/include/c++/4.2.1/bits/stl_pair.h:69: error: non-static const member ‘const std::basic_string<char, std::char_traits<char>, std::allocator<char> > std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>::first’, can't use default assignment operator
/usr/include/c++/4.2.1/bits/stl_algobase.h: In static member function ‘static _OI std::__copy<<anonymous>, <template-parameter-1-2> >::copy(_II, _II, _OI) [with _II = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, _OI = std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, bool <anonymous> = false, <template-parameter-1-2> = std::bidirectional_iterator_tag]’:
/usr/include/c++/4.2.1/bits/stl_algobase.h:268: note: synthesized method ‘std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>& std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>::operator=(const std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>&)’ first required here
Somehow this looks unnecessarily complicated to me. Is that
true and can I make it better?
BTW, I have clone() methods
in the classes I derived from shape. Perhaps I can use them
for the clone_deep method? Are they ok? They look something
like this:
class shape
{
public:
/* Many methods. */
virtual shape* clone () const = 0;
protected:
colorRGB color_;
std::string name_;
};
class triangle2d : public shape
{
public:
/* Many methods. */
triangle2d* clone() const;
private:
point3d a_, b_, c_;
};
triangle2d*
triangle2d::clone() const
{
return new triangle2d(*this);
}
Usually a clone function would return a pointer to a new instance. What you are returning is an object by value which is copy constructed from a dynamically allocated isntance that is then leaked.
If you want to return by value then you should not use new.
E.g.
shape_container shape_container::clone_shallow () const
{
return *this;
}
If the data member is just a std::map instance, then it will be copied as part of your shallow clone in any case so there is no need to do the std::copy in the deep clone case, it's not trying to do anything different.
If you wanted to do a std::copy of a map you would need to use a std::insert_iterator.
I think that it might be easier to do a clone of each shape after the fact, though.
e.g.
shape_container shape_container::clone_deep() const
{
shape_container ret(*this);
for (std::map<std::string, shape*>::iterator i = ret.data.begin(); i != ret.data.end(); ++i)
{
i->second = i->second->clone();
}
return ret;
}
First of all your example leaks memory because you new a shape_container in your methods but then it gets copied out through the return value. You should be returning pointers as with your shape example.
The compiler errors look to be related in some way to the copying since it's complaining it can't generate an assignment operator for you. Again, try using pointers and that issue should go away.
If you do deep copy of map then you have to a new create map with all element with deep copy.
Think about reference counting approach , it will be better approach.
One option is to wrap your shape type in a type that performs a deep
copy of the object:
class shape_deep_copy_wrapper {
// ...
public:
shape_deep_copy_wrapper (shape * shape)
: m_my_shape (shape)
{
}
shape_deep_copy_wrapper (shape_deep_copy_wrapper const & rhs)
: m_my_shape (rhs.m_my_shape.deep_copy ())
{
}
// ...
private:
shape * m_my_shape;
};
Then construct a map with this type:
typedef std :: map < shape_deep_copy_wrapper , ... > DeepCopy ;
typedef std :: map < shape* , ... > ShallowCopy ;