I thought this std::map key extraction into an std::vector should have worked without specifying --std=c++0x flag for gcc (4.6), but it did not. Any idea why?
template <typename Map, typename Container>
void extract_map_keys(const Map& m, Container& c) {
struct get_key {
typename Map::key_type operator()
(const typename Map::value_type& p) const {
return p.first;
}
};
transform(m.begin(), m.end(), back_inserter(c), get_key());
}
Thanks!
The reason is that you are using a local type get_key as the last argument. This was not allowed in C++98 and the rules have been changed/relaxed for C++11.
This can be seen in this example:
template <class T> bool cpp0X(T) {return true;} //cannot be called with local types in C++03
bool cpp0X(...){return false;}
bool isCpp0x()
{
struct local {} var;
return cpp0X(var);
}
Related
I need to write a comparator builder which can generate a comparator for std:sort. This builder can deal with any generic objects, and take an arbitrary data member of the object in std:vector to sort. so we need to pass in the class data member pointer to comparator_builder's constructor. The usage and the interface of this comparator_builder is shown below:
vector<T> arr;
sort( arr.begin(), arr.end(), comparator_builder( &T::data_memeber ) );
Since we don't know what objects to be sorted is before-hand, we can't know what data member will be in it. We need to also make the class member pointer generic. No idea how to implement it using template. Is there any C++ expert or genius who can give me some guidance?
The following is my code. But they can't be complied even.
template <typename ObjectType, typename MemberType >
class Comparator {
public:
Comparator ( ObjectType::data_address ) {
data_ptr = &data_address
}
bool operator()( ObjectType x, ObjectType y ) {
return x.*data_ptr < y.*data_ptr;
}
MemberType ObjectType::* data_ptr;
};
template <typename ObjectType, typename MemberType >
class Comparator_Builder{
ObjectType::member_address ;
public:
Comparator_Builder( ObjectType::mem_address ) {
member_address = mem_address;
}
Comparator < ObjectType, MemberType ObjectType::* > operator()() {
return Comparator < ObjectType, MemberType ObjectType::* >( member_address );
}
};
You're already most of the way there with your comparator class:
template <typename ObjectType, typename MemberType>
class MemberComparator {
public:
using MemberPtr = MemberType ObjectType::*;
explicit MemberComparator(MemberPtr ptr) : m_ptr(ptr) {}
bool operator()(const ObjectType& x, const ObjectType& y) const {
return x.*m_ptr < y.*m_ptr;
}
private:
MemberPtr m_ptr;
};
Just a few syntax fixes and that's all you need. Constructor template argument deduction also makes this really easy to use in C++17:
std::sort(vec.begin(), vec.end(), MemberComparator(&T::data_member));
If you don't have C++17 you either have to manually specify the template parameters or you can create a template function to do the deduction:
template <typename ObjectType, typename MemberType>
auto GetComparator(MemberType ObjectType::*ptr) {
return MemberComparator<ObjectType, MemberType>(ptr);
}
And then use it like this:
std::sort(vec.begin(), vec.end(), GetComparator(&T::data_member));
From the comments:
is it possible that we make argument passed into GetComparator() more generic? so that we can also pass in getter function, which is class function pointer, like this std::sort(vec.begin(), vec.end(), GetComparator(&T:: get_data_member) );?
Yes, we could certainly add implementations for member functions, though you'll start to run into problems if those getters are overloaded. This can be made more generic, however:
template <typename F>
auto GetComparator(F&& func) {
return [f = std::forward<F>(func)](auto&& lhs, auto&& rhs) {
return f(lhs) < f(rhs);
};
}
Now we can do this:
std::sort(vec.begin(), vec.end(), [](const auto &value) { return value.get_data_member(); });
This can likewise replace the member pointer comparator we have above by just doing e.g.:
std::sort(vec.begin(), vec.end(), [](const auto &value) { return value.data_member; });
If you like the member pointer syntax we can add overloads for that and even replace the MemberComparator class entirely:
template <typename ObjectType, typename MemberType>
auto GetComparator(MemberType ObjectType::*ptr) {
return [ptr](const ObjectType& lhs, const ObjectType& rhs) {
return lhs.*ptr < rhs.*ptr;
};
}
template <typename ObjectType, typename MemberType>
auto GetComparator(MemberType (ObjectType::*ptr)()) {
return [ptr](ObjectType& lhs, ObjectType& rhs) {
return (lhs.*ptr)() < (rhs.*ptr)();
};
}
template <typename ObjectType, typename MemberType>
auto GetComparator(MemberType (ObjectType::*ptr)() const) {
return [ptr](const ObjectType& lhs, const ObjectType& rhs) {
return (lhs.*ptr)() < (rhs.*ptr)();
};
}
I'm annoyed that STL containers don't have a, well, contains() method returning true if the container contains an element, false otherwise. So, I sat down and wrote this:
template <typename C, typename E>
inline bool contains(const C& container, const E& element) {
return container.find(element) != container.end();
}
which works well enough for sets and maps, but not for vectors. Or lists. How should I proceed? Should I write an additional
template <typename T>
inline bool contains(const vector<T>& container, const T& element) {
std::find(vector.begin(), vector.end(), item) != vector.end()
}
and more specific code for other containers? Should I instead settle on the sub-optimal use of iterators to check element-by-element? I would really much rather not do that... perhaps I'm not noticing some relevant STL functionality?
I think one reason is for the absence of a std::contains returning a bool is that it is too easy for novice programmers to fall into the trap
if (std::contains(my_container, some_element)) {
auto it = std::find(begin(my_container), end(my_container), some_element);
// process *it
}
and now you are doing twice the work you need.
It is simply idiomatic to write
auto it = std::find(begin(my_container), end(my_container), some_element);
if (it != end(my_container)) {
// process *it
}
If you insist on having a contains function, you could aim for the best of both worlds by returning a std::pair<bool, iterator> or a std::optional<iterator> (coming in a library fundamentals Technical Specification, or already present in Boost) that you can query like this:
if (opt = std::contains(my_container, some_element)) {
// process *opt
}
If you intend to use this function only on STL containers, and if you further have no need to process the iterator returned by find, then yes, I would suggest you to write specific code for these containers. It is the most effective you can do.
template<typename ... Args> struct has_find {};
template<typename T> struct has_find<std::vector<T> > { static const bool value=false; };
template<typename T> struct has_find<std::deque<T> > { static const bool value=false; };
template<typename T, size_t I> struct has_find<std::array<T, I> > { static const bool value=false; };
template<typename T, typename U> struct has_find<std::map<T, U> > { static const bool value=true; };
//... and so on for the handful remaining containers
template<bool has_find>
struct contains_impl
{
template <typename C, typename E>
bool contains(const C& container, E&& element) const
{
return container.find(std::forward<E>(element)) != container.end();
}
};
template<>
struct contains_impl<false>
{
template <typename C, typename E>
bool contains(const C& container, E&& element) const
{
return std::find(container.cbegin(), container.cend(), std::forward<E>(element)) != container.cend();
}
};
template <typename C, typename E>
bool contains(const C& container, E&& element)
{
return contains_impl<has_find<C>::value>().contains(container, std::forward<E>(element));
}
The alternative would be to use metaprogramming and let the compiler determine whether the class contains a specific find function, but that would maybe be a bit overkill...
Anyways, if want to go this way, you can read the recipes in this thread.
Context: C++03 only + the use of boost is authorized
I'd like to raise the same question as in
How to negate a predicate function using operator ! in C++?
... but with an overloaded boolean predicate, that is:
struct MyPredicate
{
bool operator()(T1) const;
bool operator()(T2) const;
};
Clearly, MyPredicate cannot be derived from std::unary_function as it is impossible to define a single argument_type.
The aim is to use MyPredicate as argument to range adaptors, with a readable syntax like this:
using boost::for_each;
using boost::adaptors::filtered;
list<T1> list1;
list<T2> list2;
for_each(list1 | filtered(!MyPredicate()), doThis);
for_each(list2 | filtered(!MyPredicate()), doThat);
Of course, any solution involving explicit disambiguation is of no interest here.
Thank you in advance.
[ACCEPTED SOLUTION]
I'm using a slightly modified version of Angew's solution:
template <class Predicate>
struct Not
{
Predicate pred;
Not(Predicate pred) : pred(pred) {}
template <class tArg>
bool operator() (const tArg &arg) const
{ return !pred(arg); }
};
template <class Pred>
inline Not<Pred> operator! (const Pred &pred)
{
return Not<Pred>(pred);
}
template <class Pred>
Pred operator! (const Not<Pred> &pred)
{
return pred.pred;
}
Note that operators && and || can benefit from this trick likewise.
You can do this:
struct MyPredicate
{
bool positive;
MyPredicate() : positive(true) {}
bool operator() (T1) const {
return original_return_value == positive;
}
bool operator() (T2) const {
return original_return_value == positive;
}
};
inline MyPredicate operator! (MyPredicate p) {
p.positive = !p.positive;
return p;
}
To address your concern of forgetting to use positive, you could try an alternative approach with a wrapper class.
template <class Predicate>
struct NegatablePredicate
{
Predicate pred;
bool positive;
NegatablePredicate(Predicate pred, bool positive) : pred(pred), positive(positive) {}
template <class tArg>
bool operator() (const tArg &arg) const
{ return pred(arg) == positive; }
};
template <class Pred>
inline NegatablePredicate<Pred> operator! (const Pred &pred)
{
return NegatablePredicate<Pred>(pred, false);
}
You can also add an overload for optimisation purposes:
template <class Pred>
inline NegatablePredicate<Pred> operator! (const NegatablePredicate<Pred> &pred)
{
return NegatablePredicate<Pred>(pred.pred, !pred.positive);
}
To address possible concern with the wide scope of the template operator!, you can employ boost::enable_if magic.
You actually can derive from std::unary_function:
template<typename T>
struct MyPredicate : std::unary_function<T, bool>
{
bool operator()(T) const;
};
I want to write my own algorithm (just a function really) that takes a range of iterators. If the iterators are from a map, I want to use the data (iterator->second) value. If the iterator is "normal" like a vector or list, I just want to use the dereferenced iterator value.
I think, value-getter idea is right here, but you can implement it without c++11 and without structs at all, only using functions:
template <typename T>
const T& get(const T& t)
{
return t;
}
template <typename T, typename V>
const V& get(const std::pair<T,V>& t)
{
return t.second;
}
int main()
{
std::vector<int> v = {1};
std::cout << get(*v.begin());
std::cout << "\n----\n";
std::map<int, std::string> m;
m.insert(std::make_pair(0, "sss"));
std::cout << get(*m.cbegin());
}
You can make a value-getter class that extracts the value you're interested in. Note that this approach doesn't work if you store pairs in any container (it transforms all pairs, whether in a map or not). I'd think it would be a much clearer approach to only accept "regular" iterators and let it be callers job to transform map iterators appropriately (as suggested in the comments to your question.)
template<typename T>
struct get {
static auto val(const T& t) -> const T&
{
return t;
}
};
template<typename U, typename V>
struct get<std::pair<U, V>> {
static auto val(const std::pair<U, V>& p) -> const V&
{
return p.second;
}
};
// use like
get<decltype(*iter)>::val(*iter);
Convenience function could look like:
template<class T>
auto getval(const T& t) -> decltype(get<T>::val(t))
{
return get<T>::val(t);
}
You can overload the function based on the input:
void foo(const std::vector<int>::iterator& it1, const std::vector<int>::iterator& it2)
{
//use *it
}
void foo(const std::map<int,int>::iterator& it1, const std::map<int,int>::iterator& it2)
{
//use it->second
}
Edit:
I think this is the closest you can get to what you want to achieve:
template <typename T, typename X>
void foo(T const& x, X const& y)
{
}
template <typename T, typename S>
void foo(const typename std::map<T,S>::iterator& x, const typename std::map<T,S>::iterator& y)
{
}
int main()
{
std::map<int,int> x;
std::vector<int> y;
foo(x.begin(), x.end()); //will call second version
foo(y.begin(), y.end()); //will call first version
}
A trait should do the trick. First the type-deducing helper:
template <typename Iter>
typename iter_value<Iter>::value_type & iter_deref(Iter it)
{
return iter_value<Iter>::deref(it);
}
All we need is something like this:
template <typename Iter>
class iter_value
{
template <typename T> struct aux
{
typedef T type;
static type & deref(Iter it) { return *it; }
};
template <typename U, typename V> struct aux<std::pair<U const, V>>
{
typedef V type;
static type & deref(Iter it) { return it->second; }
};
typedef typename std::iterator_traits<Iter>::value_type type;
public:
typedef typename aux<type>::type value_type;
static value_type & deref(Iter it)
{
return aux<type>::deref(it);
}
};
You can create a function that extracts the value out of the iterator. Then you can overload that based on the type of the iterator. You can use that function in your algorithm. Assuming a vector of ints and a map of string->int, it could look like this:
int getValue(const std::vector<int>::iterator& it)
{
return *it;
}
int getValue(const std::map<std::string, int>::iterator& it)
{
return it->second;
}
Then the algorithm can use the function getValue() to get a value from the iterator.
I need to define a get method in two different ways. One for simple types T. And once for std::vector.
template<typename T>
const T& Parameters::get(const std::string& key)
{
Map::iterator i = params_.find(key);
...
return boost::lexical_cast<T>(boost::get<std::string>(i->second));
...
}
How can I specialize this method for std::vector. As there the code should look something like this:
template<typename T>
const T& Parameters::get(const std::string& key)
{
Map::iterator i = params_.find(key);
std::vector<std::string> temp = boost::get<std::vector<std::string> >(i->second)
std::vector<T> ret(temp.size());
for(int i=0; i<temp.size(); i++){
ret[i]=boost::lexical_cast<T>(temp[i]);
}
return ret;
}
But I do not know how to specialize the function for this. Thanks a lot.
Don't specialize function template.
Why Not Specialize Function Templates?
Template Specialization and Overloading
Instead, use overload.
Write a function template get_impl to handle the general case, and overload (not specialize) this to handle the specific case, then call get_impl from get as:
template<typename T>
const T& Parameters::get(const std::string& key)
{
//read the explanation at the bottom for the second argument!
return get_impl(key, static_cast<T*>(0) );
}
And here goes the actual implementations.
//general case
template<typename T>
const T& Parameters::get_impl(const std::string& key, T*)
{
Map::iterator i = params_.find(key);
return boost::lexical_cast<T>(boost::get<std::string>(i->second));
}
//this is overload - not specialization
template<typename T>
const std::vector<T>& Parameters::get_impl(const std::string& key, std::vector<T> *)
{
//vector specific code
}
The static_cast<T*>(0) in get is just a tricky way to disambiguate the call. The type of static_cast<T*>(0) is T*, and passing it as second argument to get_impl will help compiler to choose the correct version of get_impl. If T is not std::vector, the first version will be chosen, otherwise the second version will be chosen.
Erm. call it something else? e.g.
template<typename T>
const T& Parameters::getVector(const std::string& key)
{
Map::iterator i = params_.find(key);
std::vector<std::string> temp = boost::get<std::vector<std::string> >(i->second)
// T is already a vector
T ret; ret.reserve(temp.size());
for(int i=0; i<temp.size(); i++){
ret.push_back(boost::lexical_cast<typename T::value_type>(temp[i]));
}
return ret;
}
You'll have to call this as:
foo.getVector<std::vector<int> > ("some_key");
Nothing in your question precludes this.
Now, if you really do need to use get(), then you have to rely on partially specializing a structure, as function partial specialization is not supported by the language.
This is a lot more complicated, for example:
template <typename T>
struct getter
{
const T& operator()(std::string const& key)
{
// default operations
}
};
// Should double check this syntax
template <typename T>
struct getter<std::vector<T, std::allocator<T> > >
{
typedef std::vector<T, std::allocator<T> > VecT;
const VecT& operator()(std::string const& key)
{
// operations for vector
}
};
Then in you method becomes:
template<typename T>
const T& Parameters::get(const std::string& key)
{
return getter<T>()(key); // pass the structures getter needs?
}