I am trying to write an iterator class which returns a getter function return value when it is dereferenced. The code works fine, my only problem is that I would like to write the member_ptr_functor using only one template parameter and not 3, since I am supposed to be able to deduce the types of the argument and return value from the member function type. I think the problematic one is the argument type, I tried using boost::remove_ptr&, but I couldn't compile it.
#include <iostream>
#include <vector>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/indirect_iterator.hpp>
using namespace boost;
using namespace std;
class CTest
{
private:
int m_x;
public:
CTest(int x) : m_x(x)
{
}
const int& GetX() const
{
return m_x;
}
};
template<typename MemFunType, typename ArgumentType, typename ResultType>
class member_ptr_functor : public unary_function<ArgumentType, ResultType>
{
private:
MemFunType m_MemFun;
public:
typedef ArgumentType argument_type;
typedef ResultType result_type;
member_ptr_functor(MemFunType MemFun) : m_MemFun(MemFun)
{
}
result_type operator() (argument_type arg) const
{
return m_MemFun(&arg);
}
};
template<typename MemFunType, typename ArgumentType, typename ResultType>
member_ptr_functor<MemFunType, ArgumentType, ResultType> make_member_ptr_functor(MemFunType MemFun)
{
return member_ptr_functor<MemFunType, ArgumentType, ResultType>(MemFun);
}
class CPrintFunctor : public unary_function<int, void>
{
public:
void operator() (const int n) const
{
cout << n << endl;
}
};
int main()
{
typedef vector<CTest> Container_t;
Container_t v;
v.push_back(CTest(1));
CPrintFunctor PF;
Container_t::const_iterator itStart = v.begin();
Container_t::const_iterator itEnd = v.end();
typedef member_ptr_functor<const_mem_fun_t<const int&, CTest> , CTest, const int&> member_ptr_functor_t;
member_ptr_functor_t MemberPtrFunctor = member_ptr_functor_t(mem_fun(&CTest::GetX));
typedef transform_iterator<member_ptr_functor_t, Container_t::const_iterator, const int&, const int> transform_iterator_t;
transform_iterator_t itTransformStart = make_transform_iterator(itStart, MemberPtrFunctor);
transform_iterator_t itTransformEnd = make_transform_iterator(itEnd, MemberPtrFunctor);
for_each(itTransformStart, itTransformEnd, PF);
return 0;
}
Hagai.
This does not answer your question directly but rather suggests alternative approach.
You are already using Boost, so why do you not take it one step further, use Boost.Range:
#include <boost/functional.hpp>
#include <boost/range.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/adaptor/transformed.hpp>
// ...
int main ()
{
// ...
boost::range::for_each (
boost::adaptors::transform (v, boost::mem_fun_ref (&CTest::GetX)),
PF);
}
This lets you write the functionality that you want without having to define own functors and without using too many typedefs.
Related
I'm trying to key a set of objects on a std::chrono::duration. This will not compile:
#include <unordered_map>
#include <chrono>
class Foo final
{
public:
Foo() {}
int y;
};
int main(void)
{
auto map = std::unordered_map<std::chrono::duration<int, std::milli>, Foo>();
map[std::chrono::duration<int, std::milli>(5)].y = 0;
return 0;
}
/usr/include/c++/4.9/bits/hashtable_policy.h: In instantiation of
'struct std::__detail::__is_noexcept_hash >, std::hash > > >':
I'm guessing the problem here is there's no std::hash implementation for std::chrono::duration? If not, is there a way of doing this without resorting to keying on the eminently breakable count()?
Well, you could hide count under your own std::hash implementation http://en.cppreference.com/w/cpp/utility/hash:
#include <unordered_map>
#include <chrono>
class Foo final
{
public:
Foo() {}
int y;
};
using namespace std::chrono_literals;
// custom specialization of std::hash can be injected in namespace std
namespace std
{
template<typename _rep, typename ratio>
struct hash<std::chrono::duration<_rep, ratio>>
{
typedef std::chrono::duration<_rep, ratio> argument_type;
typedef std::size_t result_type;
result_type operator()(argument_type const& s) const
{
return std::hash<_rep>{}(s.count());
}
};
}
int main(void)
{
auto map = std::unordered_map<std::chrono::duration<float, std::milli>, Foo>();
map[std::chrono::duration<float, std::milli>(5)].y = 12;
std::cout << map[5ms].y; // thanks to std::chrono_literals
return 0;
}
If you are afraid of passing different ratios into your map you could also use static_cast into some minimal time precision, eg. std::micro:
return std::hash<_rep>{}( static_cast<std::chrono::duration<_rep, std::micro>>(s).count());
Here, I tried to make a map that its vertex can be user-defined class. But when I try to add template type element to the unordered_set it gives error. The code is:
#include <iostream>
#include <unordered_set>
#include <string>
#include <vector>
#include <functional>
template<class T> class Edge;
template<class T> class Vertex{ // Made it a class just for its constructor.
public:
template<class A> Vertex(A vert){
A vertex = vert;
std::unordered_set<Edge<A>> adjlist;
}
};
template<class T> class Edge{ // Made it a class just for its constructor.
public:
template<class A> Edge(Vertex<A> vert1, Vertex<A> vert2, int w){
Vertex<A> *origin = &vert1;
Vertex<A> *target = &vert2;
}
};
template<class T>
class WUG{
private:
std::unordered_set<Vertex<T>> vertices;
std::unordered_set<Edge<T>> edges;
int num_of_edges;
int num_of_vertices;
public:
WUG() {
num_of_edges = 0;
num_of_vertices = 0;
}
void addVertex(T newVert) {
Vertex<T> temp = Vertex<T>(newVert);
vertices.emplace(temp); //Problem is here
}
int main(int argc, char** argv) {
WUG<char> g1 = WUG<char>();
g1.addVertex('A');
g1.addVertex('B');
g1.addVertex('C');
return 0;
}
Error: it opens hashtable_policy.h and gives error at
template <typename _Key, typename _Hash>
struct __is_noexcept_hash : std::integral_constant<bool,
noexcept(declval<const _Hash&>()(declval<const _Key&>()))> //Here
{ };
[Error] no match for call to '(const std::hash<Vertex<char> >) (const Vertex<char>&)'
How do you emplace a template type object to unordered_set? How about pair of 2 template?
I believe you need to provide special hashing and comparison functions to make the hash set (or in my example's case, hash map) work. Here is a minimal example. Tested with C++11.
#include <unordered_map>
#include <iostream>
#include <algorithm>
template<typename T>
struct foo {
typedef T value_type;
foo(T x) : x(x) {}
T x;
};
template<typename T>
struct foo_hasher {
int operator()(const T &val) const {
return std::hash<typename T::value_type>()(val.x);
}
};
template<typename T>
struct foo_equality {
bool operator()(const T &left, const T& right) const {
return left.x == right.x;
}
};
int main() {
typedef std::unordered_map<foo<int>, int, foo_hasher<foo<int>>, foo_equality<foo<int>>> Map;
Map mp;
foo<int> x(5);
mp[x] = 10;
mp[foo<int>(10)] = 22;
std::for_each(mp.begin(), mp.end(), [](const Map::value_type &val) {
std::cout << val.first.x << ", " << val.second << "\n";
});
}
Note that both my hashing and equality function are not at all restrictive - they are wrt T rather than foo, but the principal should be the same.
Is it possible to convert a vector of one type to another implicitly?
i.e some way to make this code work (obviously this is a simplified problem of what I am trying to do)
std::vector<int> intVec;
intVec.push_back(1);
std::vector<double> doubleVec = intVec;
std::vector<double> doubleVec2;
doubleVec2 = intVec;
No, there is no conversion (implicit or otherwise) between different vector types.
You could initialise it from an iterator range:
std::vector<double> doubleVec(intVec.begin(), intVec.end());
perhaps wrapping this in a function:
template <typename To, typename From>
To container_cast(From && from) {
using std::begin; using std::end; // Koenig lookup enabled
return To(begin(from), end(from));
}
auto doubleVec = container_cast<std::vector<double>>(intVec);
template<class T, class A=std::allocator<T>>
struct magic_vector:std::vector<T,A> {
using base=std::vector<T,A>;
using base::base;
magic_vector(magic_vector const&)=default;
magic_vector(magic_vector &&)=default;
magic_vector& operator=(magic_vector const&)=default;
magic_vector& operator=(magic_vector &&)=default;
magic_vector()=default;
template<class U, class B,
class=typename std::enable_if<std::is_convertible<U,T>::value>::type
>
magic_vector( magic_vector<U,B> const& o ):
base( o.begin(), o.end() )
{}
template<class U, class B,
class=typename std::enable_if<
std::is_convertible<U,T>::value
&& noexcept( T(std::declval<U&&>()) )
>::type
>
magic_vector( magic_vector<U,B>&& o ):
base(
std::make_move_iterator(o.begin()),
std::make_move_iterator(o.end())
)
{}
};
magic_vectors are vectors that auto convert from other magic_vectors.
If you have a pointer to a magic_vector that you convert into a pointer to vector, then delete it as a vector, the result is undefined behavior. (However in practice, there will be no harm in every C++ implementation I have checked). This is, however, a strange way to act with vectors.
Replace use of vector with magic_vector. So long as you don't have specializations on the exact type of a container in your code, it should be a drop-in replacement, except now it will auto-convert between them.
Work could be done to have magic_vectors auto-convert with vectors instead of just with magic_vectors.
One way is to create a conversion function. It allows you to express intent at the call site:
#include <iostream>
#include <vector>
template<class To, class From, class Allocator>
std::vector<To, typename Allocator::template rebind<To>::other>
implicit_convert(const std::vector<From, Allocator>& vf)
{
return { std::begin(vf), std::end(vf) };
}
template<class To, class ToA, class From, class FromA>
void implicit_overwrite(std::vector<To, ToA>& to, const std::vector<From, FromA>& from)
{
to.clear();
std::copy(begin(from), end(from), back_inserter(to));
}
int main(int argc, const char * argv[]) {
using namespace std;
std::vector<int> vi { 1, 2 , 3 };
auto vd = implicit_convert<double>(vi);
cout << "after conversion\n";
for (const auto& i : vd) {
cout << i << endl;
}
vi.push_back(4);
implicit_overwrite(vd, vi);
cout << "after copy\n";
for (const auto& i : vd) {
cout << i << endl;
}
return 0;
}
expected output:
after conversion
1
2
3
after copy
1
2
3
4
you could go for something like this (assuming myclass is your class that can be constructed from a std::pair):
#include <iostream>
#include <vector>
#include <utility>
using std::cout;
using std::endl;
class myclass
{
public:
myclass(const std::pair<int, int>& p): first_(p.first), second_(p.second) {}
int first() {return first_;}
int second() {return second_;}
private:
int first_;
int second_;
};
template <class T>
class myvector : public std::vector<T>
{
using base = std::vector<T>;
using base::base;
};
template<>
class myvector<myclass> : public std::vector<myclass>
{
public:
myvector(const std::vector<std::pair<int, int>>& vp):
std::vector<myclass>(vp.begin(), vp.end()) {}
};
int main()
{
std::vector<std::pair<int, int>> vp {{12,3}, {1, 7}};
myvector<myclass> mm = vp;
cout<<mm[0].first(); //prints 12
}
You inherit myvector from std::vector and then you specialize it for myclass. Alternatively you could define myvector in a namespace and access it as mynamespace::vector<myclass>
I am trying to create a concept for use with boost::any. This concept should say that
a class has ha member function with signatur void templateFunction(T t). I have gotten this to compile and working fine, but only for one type at a time. Is what I am trying to do impossible?
#include <iostream>
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/any_cast.hpp>
#include <boost/type_erasure/builtin.hpp>
#include <boost/type_erasure/operators.hpp>
#include <boost/type_erasure/member.hpp>
#include <boost/type_erasure/free.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/any.hpp>
using namespace std;
namespace mpl = boost::mpl;
using namespace boost::type_erasure;
class Foo
{
public:
template <class T>
void templateFunction(T t)
{
cout << t << endl;
}
};
template<class C, class T>
struct has_template_function
{
static void apply(C& cont, const T& arg) { cont.templateFunction(arg); }
};
namespace boost
{
namespace type_erasure
{
template<class C, class T, class Base>
struct concept_interface<has_template_function<C, T>, Base, C> : Base
{
void templateFunction(typename as_param<Base, const T&>::type arg)
{ call(has_template_function<C, T>(), *this, arg); }
};
}
}
int main()
{
any<has_template_function<_self, int>, _self&> c = Foo();
c.templateFunction(5);
//Compile error: cannot convert parameter 1 from 'const char [6]' to 'const int &'
//c.templateFunction("Hello");
return 0;
}
This is kind of possible by overloading, and documented in the official Boost.TypeErasure documentation.
The caveat is, as said in the comments:
You can't type-erase templates and keep their polymorphic nature
Therefore, you will have to specify the overloads explicitly in the requirements for your boost::typeerasure::any type.
You need to modify your concept interface as described in the docs, and add a string overload to the requirements section.
Your example, modified to handle overloads:
#include <iostream>
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/any_cast.hpp>
#include <boost/type_erasure/builtin.hpp>
#include <boost/type_erasure/operators.hpp>
#include <boost/type_erasure/member.hpp>
#include <boost/type_erasure/free.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/any.hpp>
#include <string>
#include <utility>
using namespace std;
namespace mpl = boost::mpl;
using namespace boost::type_erasure;
struct FooStruct
{
template <class T>
void templateFunction(T t)
{
cout << t << endl;
}
};
template<class T, class U>
struct has_template_function
{
static void apply(T& t, const U& u) { t.templateFunction(u); }
};
namespace boost {
namespace type_erasure {
template<class T, class U, class Base, class Enable>
struct concept_interface< ::has_template_function<T, U>, Base, T, Enable> : Base
{
typedef void _fun_defined;
void templateFunction(typename as_param<Base, const U&>::type arg)
{
call(::has_template_function<T, U>(), *this, arg);
}
};
template<class T, class U, class Base>
struct concept_interface< ::has_template_function<T, U>, Base, T, typename Base::_fun_defined> : Base
{
using Base::templateFunction;
void templateFunction(typename as_param<Base, const U&>::type arg)
{
call(::has_template_function<T, U>(), *this, arg);
}
};
}
}
ostream& operator<<(ostream& os, const std::pair<int, string>& pair) {
os << "(" << pair.first << ", " << pair.second << ")";
return os;
}
int main()
{
any<
mpl::vector
<
has_template_function<_self, int>,
has_template_function<_self, std::string>,
has_template_function<_self, std::pair<int,std::string>>
>
, _self&> c = FooStruct();
c.templateFunction(5);
c.templateFunction("Hello");
c.templateFunction(std::make_pair(5, "Hello"));
return 0;
}
HI,
I don't like posting compile problems, but I really can't figure this one out. Using this code:
#include <map>
#include <boost/iterator/transform_iterator.hpp>
using namespace std;
template <typename K, typename V>
struct get_value
{
const V& operator ()(std::pair<K, V> const& p) { return p.second; }
};
class test
{
typedef map<int, float> TMap;
TMap mymap;
public:
typedef get_value<TMap::key_type, TMap::value_type> F;
typedef boost::transform_iterator<F, TMap::iterator> transform_iterator;
transform_iterator begin()
{
return make_transform_iterator(mymap.begin(), F());
}
};
Getting this compile error:
transform_iterator.hpp(43) : error C2039: 'result_type' : is not a member of 'get_value<K,V>'
with
[
K=int,
V=std::pair<const int,float>
]
Can anyone explain why this isn't working? I'm using Visual Studio 7.0 with boost 1.36.0
Thanks.
Since you also asked for an explanation
The transform_iterator needs to know the return type of the function called in order to instantiate itself. This is determined via result_of (found in <boost/utility/result_of.hpp>
If you use a function object, you need to define a member result_type to specify the result type of the object. (since an object doesn't have a 'return type' as such)
If you would have used a regular function, result_of would be able to figure it out on his own, e.g.:
template <typename K, typename V>
const V & get_value(std::pair<K, V> const & p) { return p.second; }
class test
{
typedef map<int, float> TMap;
TMap mymap;
public:
typedef boost::function< const TMap::mapped_type & (const TMap::value_type &) > F;
typedef boost::transform_iterator<F, TMap::iterator> transform_iterator;
transform_iterator begin()
{
return boost::make_transform_iterator(mymap.begin(), &get_value< int, float >);
}
};
You'll have to inherit get_value from unary_function<const V&, std::pair<K, V> const&> to tell transform_iterator what the signature of get_value is.
// here is a working example:
#include <vector>
#include <iostream>
#include <boost/iterator/transform_iterator.hpp>
template <typename T, typename U>
const T& Get1st(const std::pair<T, U>& pair) { return pair.first; }
struct Bar {
using Pairs = std::vector<std::pair<int, char>>;
using Iter = boost::transform_iterator< decltype(&Get1st<int, char>), Pairs::const_iterator >;
void add(int i, char c) { _pairs.emplace_back(i, c); }
Iter begin() { return boost::make_transform_iterator(_pairs.begin(), &Get1st<int, char>); }
Iter end() { return boost::make_transform_iterator(_pairs.end(), &Get1st<int, char>); }
private:
Pairs _pairs;
};
int main() {
Bar bar;
bar.add(1, 'a');
bar.add(3, 'c');
bar.add(2, 'b');
for(const auto& i : bar) std::cout << i << " ";
std::cout << "\n";
return 0;
}
// outputs: 1, 3, 2