I'm working in C++98 and I want to bind std::max. But I need a functor object to use with std::bind1st.
I've tried just using std::pointer_to_binary_function but the problem seems to be that I can't make a functor out of std::max: https://stackoverflow.com/a/12350574/2642059
I've also tried std::ptr_fun but I get a similar error.
Because of the issue in this answer, you can't write a true wrapper functor for max because you can't make any of the types const T&. The best you can do is:
template <typename T>
struct Max
: std::binary_function<T, T, T>
{
T operator()(T a, T b) const
{
return std::max(a, b);
}
};
std::bind1st(Max<int>(), 1)(2) // will be 2
But that sucks, since you now have to copy everything (although if you're just using ints, this is totally fine). Best would probably be to just avoid bind1st altogether:
template <typename T>
struct Max1st
{
Max1st(const T& v) : first(v) { }
const T& operator()(const T& second) const {
return std::max(first, second);
}
const T& first;
};
Related
I need a 'MultiStack' taking different types of objects, putting each type in a separate stack.
This is what it looks like so far. The open problem is: how to handle the containers for a number of different T
class MultiStack
{
public:
template<typename T>
const T& Get()
{
return Container<T>.back();
}
template<typename T>
void Push( const T& t )
{
Container<T>.push_back( t );
}
template<typename T>
void Pop( const T& /*t*/ )
{
Container<T>.pop_back();
}
private:
// this does not make sense, we obv. need one stack for each T
// template<typename T>
// std::vector<T> Container;
};
Now, I could use the old trick, putting the Container in a member function, like
template<typename T>
auto GetContainer()
{
static std::vector<T> C;
return C;
}
but I don't like this anymore in the age of multi-threading. It is 'dangerous', right!?
Is there a better, elegant way? It is conceivable that I know the allowed types beforehand, if that helps realizing it.
but I don't like this anymore in the age of multi-threading. It is 'dangerous', right!?
Issue is not multi-threading. initialization would be fine.
You still have to protect/synchronize access though, as regular multi-threading code.
Issue is that the container is not per instance of MultiTask, as it is static.
It is mostly as if MultiTask were a Singleton.
It is conceivable that I know the allowed types beforehand, if that helps realizing it.
That helps, you can then use std::tuple, something like (C++14):
template <typename ... Ts>
class MultiStack
{
public:
template<typename T>
const T& Get() const
{
return GetContainer<T>().back();
}
template<typename T>
void Push(const T& t)
{
GetContainer<T>().push_back(t);
}
template <typename T>
void Pop()
{
GetContainer<T>().pop_back();
}
private:
template <typename T>
const std::vector<T>& GetContainer() const { return std::get<std::vector<T>>(Containers); }
template <typename T>
std::vector<T>& GetContainer() { return std::get<std::vector<T>>(Containers); }
private:
std::tuple<std::vector<Ts>...> Containers;
};
In a template function a std::vector shall get sorted. T can be a simple type or a std::pair e.g.,
std::vector<double> or
std::vector<std::pair<int,Something> >
When T is a pair then only the first element shall be compared. How can I implement the comparator for the two cases?
I have tried:
template<typename T>
inline bool smaller(const T& a,const T& b)
{
return a<b;
}
template<typename T,typename S>
inline bool smaller(
const std::pair<T,S>& a,
const std::pair<T,S>& b
)
{
return a.first<b.first;
}
template<typename T> inline void function(std::vector<T >& vVec)
{
...bla...
sort(vVec.begin(),vVec.end(),smaller<T>);
...bla...
}
but it does not work this way. I have also tried specialization but I do not find the right syntax to specialize the smaller() function.
You could just wrap it in a lambda:
std::sort(vVec.begin(),vVec.end(), [](const auto& a, const auto& b) { return smaller(a, b); });
One easy work around is to make both of your smaller functions opeator()'s of a smaller struct. Using
struct smaller
{
template<typename T>
bool operator()(const T& a,const T& b)
{
return a < b;
}
template<typename T, typename S>
bool operator() (const std::pair<T, S>& a, const std::pair<T, S>& b)
{
return a.first < b.first;
}
};
allows you to just pass a smaller to sort like
template<typename T> inline void function(std::vector<T >& vVec)
{
sort(vVec.begin(),vVec.end(),smaller{});
}
and in sort overload resolution will kick in on the two operator() smaller has and for any std::vector<std::pair>, the std::pair overload will be called.
I'm having a problem with partial template specialization.
I have this little helper template and partial specialization:
template<typename T>
struct ctor_std_vector_get
{
static_assert(false,"ERROR");
};
template<typename T>
struct ctor_std_vector_get<const std::vector<T>>
{
static const T& get(const T& x){
return x;
}
};
And then, I use it something like this:
template<typename T>
class container
{
public:
container(const std::vector<T>& inp):
{
alloc();
for( const T& t : inp){
const T& x = ctor_std_vector_get<T>::get(t);
}
}
}
But when I compile, I hit the static_assert, when I want the partial specialization. I think I've done something wrong, since if the partial specialization was a match, it would be selected before the base template. What's wrong?
container(const std::vector<T>& inp):
{
alloc();
for( const T& t : inp){
const T& x = ctor_std_vector_get<T>::get(t);
}
}
Let's say you passed a std::vector<int> as a parameter to this function.
Therefore, the T part, in const std::vector<T>& would be int. Simple substitution.
Now that we've established that T is substituted by int, which template do you expect that ctor_std_vector_get<T>, or ctor_std_vector_get<int> wind up using, the default template, or the specialization?
I want to define a templated functor for name comparison, that takes references as well
as pointers. I want to use this for a normal find_if on a container of elements as well as for a container of pointers (unfortunately ptr_vector or the like is not an option).
The best solution I have found so far is the following.
template <typename U>
class by_name{
public:
by_name(U const& pName):mName(pName) {}
template <class T>
typename boost::disable_if_c<boost::is_pointer<T>::value, bool>::type
operator()(T const& pX){ return pX.getName()== mName;}
template <class T>
typename boost::enable_if_c<boost::is_pointer<T>::value, bool>::type
operator()(T pX){ return pX->getName()== mName;}
private:
U mName;
};
This looks quite ugly and very hard to understand for people not knowing enable_if.
Is there an easier way to write such a functor taking pointer and reference alike?
It can be as simple as:
template <class T>
bool operator()(T const& rX) const { return rX.getName() == mName; }
template <class T>
bool operator()(T* const pX) const { return pX->getName() == mName; }
Do the classes that implement getName member functions return anything else than std::string? If not, you can get rid of one template parameter.
This is how I would have implemented the functor:
class by_name
{
public:
by_name(const std::string& name) :
Name(name) {}
template <class T>
bool operator()(T const& pX) const
{
return pX.getName() == Name;
}
template <class T>
bool operator()(T* pX) const
{
if (!pX) // how do you handle a null ptr?
return false;
(*this)(*pX); // #Luc Danton
}
private:
std::string Name;
};
If the pointer version is implemented as
bool operator(T const* pX) const {}
gcc for some reason choose to instantiate
bool operator(T const& pX) const with [T = A*]
The functor has been compiled and tested with gcc 4.6.1.
For simplicity, let's say I want to do implement a function which takes two parameters and predicate which test for equality,
template<typename T, typename TCompare>
bool Eq(const T& a, const T& b, const TCompare& cmp) {
return cmp(a, b);
}
but I also want that operator== is assumed if predicate is not passed.
I tried several different approaches, but all resulted in either syntax error or "operator==" not defined. I even tried replacing the Eq function with a
Nevertheless, I suppose what I want is possible since the big part of STL supports not passing the optional TCompare parameter (std::sort, std::set ...).
UPDATE:
Thanks to levis501 suggestion, this is the best way I have found so far:
template<typename T, typename TCompare>
bool Eq(const T& a, const T& b, const TCompare& cmp) {
return cmp(a, b); // or some lengthy code
}
template<typename T>
bool Eq(const T& a, const T& b) {
static std::equal_to<T> EqCmp;
return Eq(a, b, EqCmp);
}
So, you basically need to create a wrapper which passes std::equal_to, or any other operator-equivalent functor. For some reason, having it as a default argument does not compile when you invoke the function without it.
How about std::equal_to ? http://www.cplusplus.com/reference/std/functional/equal_to/
You can overload functions, no?
// Use the user-supplied TCompare.
template<typename T, typename TCompare>
bool Eq(const T& a, const T& b, TCompare cmp) {
return cmp(a, b);
}
// Use op== for equality otherwise.
template<typename T>
bool Eq(const T& a, const T& b) {
return a == b;
}
If the code calls Eq() with three arguments, the compiler will resolve the call to the first overload. If the code calls Eq() with only two arguments, then the compiler will have to resolve to the second overload.
I don't suppose something like the following would work for you:
#include <functional>
template<typename T, typename TCompare = std::equal_to<T>>
class Math {
public:
static bool Eq(const T& a, const T& b) {
TCompare cmp;
return cmp(a, b);
}
};
int _tmain(int argc, _TCHAR* argv[]) {
Math<int>::Eq(1,1);
return 0;
}
Default template parameters are only allowed on class templates (or at least that's what MSVC 10 says)