I have 2 overloaded function say - func1 and func2 -
Func1 is -
template<typename T1, typename T2> bool AreIdentical(const std::pair<T1, T2>
&lhs, const std::pair<T1, T2> &rhs)
{
//some code
}
Func2 is -
template<typename T> bool AreIdentical(typename std::map<int,
std::vector<T>>::iterator itOrig,
typename std::map<int, std::vector<T>>::iterator itNew)
{
//some code
}
I am trying to call the function AreIdentical in below manner -
int main()
{
std::map<int, std::vector<int>> orgitem;
std::map<int, std::vector<int>> newitem;
newitem[0];
orgitem[0];
AreIdentical(*orgitem.begin(), *newitem.begin());
return 0;
}
Now, interesting thing is, my origitem and newitem is of map type but always Func1 is getting called which takes parameter pair type instead of Func2.
Do anyone have any clue why is it happening so?
orgitem.begin() is an iterator. But *orgitem.begin() is the object the iterator points at, which is a std::pair<const int, std::vector<int>>.
If you had
AreIdentical(orgitem.begin(), newitem.begin());
without the dereferencing * operators, that would not be able to call the pair overload.
But in fact it won't work either, because in your second overload the parameter T is not in a deducible context. The only way to call it is:
AreIdentical<int>(orgitem.begin(), newitem.begin());
You might be able to "fix" this by changing the iterator overload to just accept any iterator whose value type has members first and second:
template <typename Iter>
auto AreIdentical(Iter itOrig, Iter itNew)
-> decltype((*itOrig).first, (*itOrig).second, bool{});
Related
I have a templated class which looks as follows (assume a using namespace std for brevity):
template <typename Type, typename Compare = less<Type>>
struct weighted_base
{
typedef typename set<pair<Type, double>, set_compare<Type, Compare>> mapped_type;
map<Type, mapped_type, Compare> backing_map;
...
};
where set_compare is defined as:
template <typename Type, typename Compare>
struct set_compare
{
bool operator()(const pair<Type, double>& a,
const pair<Type, double>& b)
{
return Compare(a.first, b.first);
}
};
That is, the map takes keys of type Type to std::set<std::pair<Type, double>> values. This has some problems when I use a method such as:
void insert(const Type& from, const Type& to, double weight)
{
//...
mapped_type& adj_nodes = backing_map[from];
adj_nodes.insert(make_pair(to, weight));
}
The problem is that within the set, when it goes to call set_compare, it has a type of const Type&, not Type. Thus, assuming it's std::less, in this case it will be trying to call less<int>::less(const int& a, const int& b) which fails.
Is there some way of fixing it so that both contains can use (effectively) the same comparison function here?
Compare is the type of a binary functor, so you probably need
return Compare()(a.first, b.first);
where Compare() is a temporary, defualt constructed, Compare instance. For example, if you substitute Compare for std::less<int>,
std::cout << std::boolalpha;
std::cout << std::less<int>(5,50) << "\n"; // Error!
std::cout << std::less<int>()(5,50) << "\n"; // OK
Your error is likely to give you many compiler errors, some of which could send you down the wrong track. I suggest fixing it first, then seeing if the code behaves as you expect it to.
First of, I'm using C++11 (and my topic sucks).
What I'm trying to do is write a generic template function that implements something usually called sort_by in other programming languages. It involves calculating an arbitrary criterion for each member of a range exactly once and then sorting that range according to those criteria. Such a criterion doesn't have to be a POD, all it has to be is less-than-comparable. For things for which std::less doesn't work the caller should be able to provide her own comparison functor.
I've successfully written said function which uses the following signature:
template< typename Tcriterion
, typename Titer
, typename Tcompare = std::less<Tcriterion>
>
void
sort_by(Titer first, Titer last,
std::function<Tcriterion(typename std::iterator_traits<Titer>::value_type const &)> criterion_maker,
Tcompare comparator = Tcompare()) {
}
It can be used e.g. like this:
struct S { int a; std::string b; double c; };
std::vector<S> s_vec{
{ 42, "hello", 0.5 },
{ 42, "moo!", 1.2 },
{ 23, "fubar", 0.2 },
};
sort_by1< std::pair<int, double> >(
s_vec.begin(), s_vec.end(),
[](S const &one_s) { return std::make_pair(one_s.a, one_s.c); }
);
What I don't like about this approach is that I have to provide the Tcriterion argument myself because the compiler cannot deduce that type from the lambda expression. Therefore this does not work:
sort_by1(s_vec.begin(), s_vec.end(), [](S const &one_s) { return std::make_pair(one_s.a, one_s.c); });
clang 3.1 and gcc 4.7.1 both bark on this (gcc 4.7.1 even barks on the code above, so I guess I'm really doing something wrong here).
However, if I assign the lambda to a std::function first then at least clang 3.1 can deduce the argument, meaning this works:
typedef std::pair<int, double> criterion_type;
std::function<criterion_type(S const &)> criterion_maker = [](S const &one_s) {
return std::make_pair(one_s.a, one_s.c);
};
sort_by1(s_vec.begin(), s_vec.end(), criterion_maker);
So my questions are: How do I have to change my function signature so that I don't need to specify that one argument? And (probably related) how would I fix my example to have it working with gcc?
Don't use std::function in tandem with template argument deduction. In fact, there's very likely no reason to use std::function in a function or function template argument list. More often than not, you should not use std::function; it is a very specialized tool that is very good at solving one particular problem. The rest of the time, you can dispense with it altogether.
In your case you don't need template argument deduction if you use a polymorphic functor to order things:
struct less {
template<typename T, typename U>
auto operator()(T&& t, U&& u) const
-> decltype( std::declval<T>() < std::declval<U>() )
{ return std::forward<T>(t) < std::forward<U>(u); }
// operator< is not appropriate for pointers however
// the Standard defines a 'composite pointer type' that
// would be very helpful here, left as an exercise to implement
template<typename T, typename U>
bool operator()(T* t, U* u) const
{ return std::less<typename std::common_type<T*, U*>::type> {}(t, u); }
};
You can then declare:
template<typename Iter, typename Criterion, typename Comparator = less>
void sort_by(Iter first, Iter last, Criterion crit, Comparator comp = less {});
and comp(*ita, *itb) will do the right thing, as well as comp(crit(*ita), crit(*itb)) or anything else as long as it makes sense.
How about something like this:
template< typename Titer
, typename Tmaker
, typename Tcompare
>
void
sort_by(Titer first, Titer last,
Tmaker criterion_maker,
Tcompare comparator)
{
typedef decltype(criterion_maker(*first)) Tcriterion;
/*
Now that you know the actual type of your criterion,
you can do the real work here
*/
}
The problem is that you can obviously not use a default for the comparator with this, but you can easily overcome that by providing an overload that doesn't take a comparator and fills in std::less internally.
To do it like you originally suggested, the compiler would have to be able to "invert" the template instantiation process. I.e. for a given std::function<> instantiation, what parameter do I have to supply as the result to get it. This "looks" easy, but it is not!
You can use also something like this.
template< typename Titer
, typename Tmaker
, typename TCriterion = typename
std::result_of
<
Tmaker
(
decltype(*std::declval<Titer>())
)
>::type
, typename Tcompare = std::less<TCriterion>
>
void
sort_by(Titer first, Titer last,
Tmaker criterion_maker, Tcompare comparator = Tcompare())
{
}
http://liveworkspace.org/code/0aacc8906ab4102ac62ef0e45a37707d
Is it possible to return an empty pair from a function? Meaning, follow the rules of the function prototype, but do not have any elements in the pair (e.g. NULL). Understanding that a pair simply exists so I don't know if this is conceptually possible. I have a need to return a pair that is NULL or empty, if that makes any sense.
For example,
pair<int, int> MyClass::someFunction()
{
// do something that means we need to return an empty pair
return NULL; // <--- this does not work obviously
}
Unfortunately, boost is not a possibility for me.
Generally speaking an empty pair doesn't even make sense. Afterall a pair is per definition a container containing two objects.
You could however make something like an empty pair using Boost.Optional. Then you would either use a boost::optional<std::pair<...>> giving you the option of returning either a pair or an empty state or use std::pair<boost::optional<...>, boost::optional<...>> for a pair where either object could be empty.
You can returns pointer... Or use boost::optional<T>. Optional will be better...
boost::optional<std::pair<int, int> > MyClass::someFunction()
{
return boost::optional<std::pair<int, int> >();
}
void f(const MyClass& f)
{
boost::optional<std::pair<int, int> > ret = f.someFunction();
if (!ret) // empty
{
...
}
}
The answer to your questions is easily explained by considering the way the C++ compiler generates code in this case.
The std::pair<int, int> is returned-by-value.
Since MyClass::someFunction() is returning an object by value, the sequence of events is as follows:
The calling function reserves space on the stack for a std::pair<int, int>
The MyClass::someFunction() is called
The right hand side of the return statement is a assignment to the location reserved on the stack earlier. There is an implicit construction of a std::pair<int, int> taking place.
Thus returning a NULL pointer is impossible.
It wouldn't take much to create your own "optional pair" (similar to boost::optional<std::pair<…>>, but with a different interface), e.g.:
template <typename T1, typename T2> struct OptPair : std::pair<T1, T2>
{
typedef std::pair<T1, T2> base_t;
bool contains;
OptPair() : contains(true) {}
explicit OptPair(bool x) : contains(x) {}
OptPair(const T1& x, const T2& y) : base_t(x, y), contains(true) {}
template <class U, class V>
OptPair(const std::pair<U,V> &p) : base_t(p), contains(true) {}
template <class U, class V> OptPair(const OptPair<U,V> &p) : base_t(p), contains(p.contains) {}
// No need to define operator=, as the default will construct an OptPair<T1, T2>
// if necessary, then copy members into *this.
};
template <typename T1, typename T2>
OptPair<T1, T2> makeOptPair() { return OptPair<T1, T2>(); }
template <typename T1, typename T2>
OptPair<T1, T2> makeOptPair(const T1 &x, const T2 &y) {
OptPair<T1, T2> p(true);
p.first = x;
p.second = y;
return p;
}
template <typename OS, typename T1, typename T2>
OS &operator<<(OS &os, const OptPair<T1, T2>& p) {
os << "<OptPair: ";
if (p.contains) os << p.first << ", " << p.second;
else os << "empty";
os << ">";
return os;
}
Then you can use it just like std::pair (and even use it interchangeably with std::pair, assigning values back and forth), but with the added ability to pass an "empty" value back like this:
OptPair<int, int> someFunction()
{
...
return OptPair<int, int>(false);
}
You have to make sure to check the result before using it, like this:
void doStuffWithPair(std::pair<int, int>);
void doStuffWithEmpty();
...
OptPair<int, int> ret = someFunction();
if (ret.contains) doStuffWithPair(ret);
else doStuffWithEmpty();
A pair, by definition, has 2 elements. It cannot have none.
You need something like boost::optional<std::pair<T1,T2>>. Then you can choose to have a pair or not. You can find documentation for boost::optional here.
I have a template class template<typename T, typename R>. R is of type vector<T*> or list<T*>.
I want my class to overload [] operator so that in case it is a vector I will use the built in [] operator for efficiency and in case it's a list I will implement it with iterator.
To me it sounds like a job for template specialization so I thought to write something like this:
template<typename T, typename R>
T& tContainer_t<T, R>::operator[]( unsigned i )
{
//TODO with iterators
}
template<>
T& tContainer_t::operator[]<T, std::vector<T*> >( unsigned i )
{
// TODO with built in [] operator
}
This is wrong and the compiler doesn't allow this.
Is there a way to make it work, or should I use typeid() to differ the two objects at runtime and act accordingly ?
The way to do it with templates is to make a static helper function in a class that can be partially specialized. However, what I would do is:
template<typename T, typename R>
T& tContainer_t<T, R>::operator[]( unsigned i )
{
//assuming that the container refernce is name container;
typename R::iterator itr = container.begin();
std::advance(itr, i);
return *itr;
}
std::advance is guaranteed that for a container with random access iterators (such as vector), it is constant time (basically, it does iterator + n), it can be as fast as doing the pointer lookup vector performs. Otherwise, it does iterator++ n times, which will be linear time. The const version will use const_iterator, but is essentially the same.
Doing it this way will let you properly handle different types of containers (not just vector and list), without having to modify the code.
You don't have to overload the operator. The library aleady contains overloaded functions to help you. std::advance will move an iterator, taking advantage of operator+() for random access iterators.
template<typename T, typename R>
T& tContainer_t<T, R>::operator[]( unsigned i )
{
typename R::iterator it = myContainer.begin();
std::advance(it, i);
return *it;
}
Normally someone would just go and grab Boost's Function Output Iterator but I'm not allowed to use Boost at work. That said, I just want to use the copy function to traverse a collection, call a function on each item, take the output of that function, and finally push_back it onto another collection. I've written some code:
#include <iterator>
using std::iterator;
using std::output_iterator_tag;
template<typename Container, typename Function>
struct Back_Transform_Iterator : public iterator<output_iterator_tag,void,void,void,void>{
explicit Back_Transform_Iterator(Container &_container, const Function &_function)
: m_Container(_container),
m_Function(_function){}
Back_Transform_Iterator<Container,Function>& operator= (const typename Function::argument_type &value){
m_Container.push_back( m_Function( value ) );
return *this;
}
Back_Transform_Iterator<Container,Function>& operator* (){ return *this; }
Back_Transform_Iterator<Container,Function>& operator++ (){ return *this; }
Back_Transform_Iterator<Container,Function> operator++ (int){ return *this; }
typedef Container container_type;
private:
Container &m_Container;
Function m_Function;
};
template<typename C, typename F>
Back_Transform_Iterator<C,F> back_transform_inserter(C &_container, F &_unary_function){
return Back_Transform_Iterator<C,F>( _container, _unary_function );
}
but... I'm getting compilation problems. Fairly certain it's to do with the operator*() call. I have no idea how to effectively dereference the container's objects so that they object the function's effects. Error:
error C2582: 'operator =' function is unavailable in 'Back_Transform_Iterator<Container,Function>'
the items I'm iterating over are not mutable. Anyone know how to tackle this issue?
You can use transform instead:
transform(src.begin(), src.end(), back_inserter(container), func);
Note that const applied on a reference type is a no-op. So if argument_type is T&, then saying const argument_type does not yield back const T& but T& again. So if your source items are constant you would try to bind them to the non-const reference parameter of operator= in case that argument_type is a reference:
typedef int &intr;
const intr& a = 0; // fails - "const" is ignored!