C++ how to pass method as a template argument - c++

Suppose I have a class X:
class X {
// ...
size_t hash() const { return ...; }
};
I would like to create a std::tr1::unordered_map<X, int, HashFn> where I want to pass in
X::hash() as HashFn. I know I can declare my own functor object. I feel that
there should be a way to do this by directly passing a pointer to X::hash().
Is there?

No; as you've shown it, you need a small utility struct:
#include <functional>
template<typename T, std::size_t (T::*HashFunc)() const = &T::hash>
struct hasher : std::unary_function<T, std::size_t>
{
std::size_t operator ()(T const& t) const
{
return (t.*HashFunc)();
}
};
Then you can create an unordered_map like so:
std::tr1::unordered_map<X, int, hasher<X> > m;

No, there isn't. The reason is that whatever is used as your HashFn must take a single argument which is a const reference to an object in the container. X::hash takes a single argument which is a const pointer to an object in the container (the this pointer is an implicit first argument in this case), so using that function by it self is not possible.
You probably use some bind magic, using boost::lambda and boost::bind. I'm not exactly sure how, but it would probably look something like this:
boost::bind(&X::hash, &_1);
Which creates a function object which will call X::hash with a pointer.

size_t hash() const { return ...;}
A function which calculates hash value takes one parameter of type Key which your function doesn't take. Hence its signature is wrong to begin with.
Since you want to implement a function, rather than a functor, here is how it should be done:
size_t hash(const KeyType &key)
{
return /*calculate hash and return it*/;
}
Make it static member function and pass it as X::hash or make it a free function, is your choice.

You can't directly, but you can wrap it. The easy way to do so is to use boost::mem_fn(), or the standard equivalents if your compiler supports them: tr1::mem_fn() (from TR1) or std::mem_fn() (from C++11).
EDIT: Actually it's not so simple. mem_fn() will work fine for a function parameter, but since its return type is unspecified it's difficult to use as a template parameter. If you have C++11 support you could use decltype to find the type; otherwise you're probably best off writing your own function object as you mentioned.

Related

std::is_const & Co with value-type wrappers as std::reference_wrapper

This might be a bit of an academic example (in the sense that I don't see it having a real use case as-is), but I have come across this line of thought a couple of times without coming up with a satisfying answer.
For the sake of argument, let's suppose that I have a template function that I want to behave differently depending on whether the passed value is const or not. A very simple example might be
template< typename T > void print_constness(T&& t) {
if constexpr (std::is_const_v< decltype(t) >) {
std::cout << "T is const\n";
} else {
std::cout << "T is NOT const\n";
}
}
If I pass a mutable reference to this function, it will correctly detect it as non-const. If I pass a const reference to it, then it correctly detects it as const (provided I can prevent the function from making a copy, e.g. by deleting the copy constructor).
Conceptually, std::reference_wrapper< T > is supposed to represent the same type as const T &. Therefore, one might expect that the result from passing a const T to that function is the same as passing a std::reference< const T >.
But this is not the case, since the wrapper itself is not const. However, for practical purposes, it is. Consider e.g. a template function that has to call a const or non-const overload of a function. When passed a std::reference_wrapper< const T >, it will pass it to the non-const overload and as soon as that tries to access the reference the compiler will complain (rightfully so).
(Note that I deliberately ignored that you can overload on the constness of your argument - my above example shall only serve as an illustration).
My question is: How to detect and in further steps modify constness of value-type wrappers such as std::reference_wrapper when the standard std::is_const, std::add_const and std::remove_const clearly don't work?
Is there a generic/standard solution to this problem or would it require implementing custom is_const, ... traits that specialize on the value wrappers that one expects to encounter?
If so: is it perhaps possible for the implementers of such wrappers to specialize the std type traits so they produce the (semantically) expected result? I kinda expect this to be forbidden...
If you have C++20, there's std::unwrap_reference:
#include <type_traits>
template<typename T>
using remove_reference_and_wrapper_t =
std::remove_reference_t<std::unwrap_reference_t<std::remove_reference_t<T>>>;
template<typename T>
constexpr static bool is_semantically_const_v =
std::is_const_v<remove_reference_and_wrapper_t<T>>;
static_assert(is_semantically_const_v<const int>);
static_assert(is_semantically_const_v<const int&>);
static_assert(is_semantically_const_v<const int&&>);
static_assert(!is_semantically_const_v<int>);
static_assert(!is_semantically_const_v<int&>);
static_assert(!is_semantically_const_v<int&&>);
static_assert(is_semantically_const_v<std::reference_wrapper<const int>>);
static_assert(!is_semantically_const_v<std::reference_wrapper<int>>);
It's a little unwieldy, but it works.
You can then use the type returned by remove_reference_and_wrapper_t to further manipulate the object; i.e., get a reference to the actual object:
remove_reference_and_wrapper_t<decltype(t)>& underlying = t;

is there anyway pass function as template parameter?

i have been working on a project and i need to know that is there anyway passing a function to template class? lets say i want this to perform sinus or cosinus function
#ifndef INTEGRAL_H
#define INTEGRAL_H
template<class F>
class Integral
{
public:
Integral( F func):f_(func){}
~Integral()=default;
Integral(){
int a,b,N;
double h=(b-a)/N;
sum=0.0;
for (size_t j=0; j<N;++j)
{
sum+=f_(a+j*h); // here i would like to perform sin(a+j*h) or cosinus or somethingelse
}
sum*=h;
}
double Sum(){return sum;}
private:
F f_;
double sum;
};
#endif // INTEGRAL_H
Your code works "as coded" (after a small fix in the constructor, unrelated to the question). But std::sin doesn't name a single function, and you can't pass it into Integral directly. The simplest way is to wrap it into a lambda:
Integral i([](auto arg) { return std::sin(arg); });
double value = i.Sum();
If your compiler doesn't support template argument deduction (available since C++17), you have to be more verbose:
auto my_sin = [](auto arg) { return std::sin(arg); };
Integral<decltype(my_sin)> i(my_sin);
double value = i.Sum();
This might help: Function passed as template argument
In the end, a function is nothing but an address to a particular place in memory which boils down to a simple number and that is something that the template system supports.
However, in your case I would recommend just passing an std::function object which is a glorified function pointer as a regular parameter to your function - omitting the need for a template (at least for this part of the functionality).
is there anyway pass function as template parameter?
Yes. Example:
template<return_type (template_argument_name)(argument_list)>
Another approach is to pass a callable type as template parameter, and invoke an object of that type. This is in fact what you've done in your example.

c++: portable solution to cast and compare member-function pointers

Before I ask what I want to know, here's a little background:
I'm wrapping a std::function in my own class Function, which stores some additional data along with the std::function object. Later on, I have a std::vector<Function<Signature>> that stores a whole bunch of Function's of the same signature (e.g. void(int)). These std::function's may represent normal free functions, functors, or member functions that have been bound to an object using std::bind.
At some later point, I want to traverse the std::vector, and check some properties of the Function objects. For example, I want to select every Function that is bound to a particular member-function (regardless of the object it will be called on). This means I have to find a way to store these member-function pointers, while discarding their exact type. In other words, I need to be able to store a pointer of type void (A::*)() and another pointer of type void (B::*)() in the same field.
I used to do this using a union to 'cast' the member-function-pointer to a void*, but then found out that member-function-pointers are implementation-defined and don't have the same size as pointers. Now I'm looking for a portable solution, and this is what I came up with:
class MemFunPtr
{
friend bool operator==(MemFunPtr const &lhs, MemFunPtr const &rhs);
enum { SIZE = sizeof(void(MemFunPtr::*)()) };
char buf[SIZE];
public:
template <typename T, typename R, typename ... Args>
MemFunPtr(R (T::*ptr)(Args ...))
{
union
{
R (T::*memfcn_)(Args ...);
char buf_[SIZE];
} caster;
caster.memfcn_ = ptr;
memcpy(buf, caster.buf_, SIZE);
}
};
bool operator==(MemFunPtr const &lhs, MemFunPtr const &rhs)
{
return memcmp(lhs.buf, rhs.buf, MemFunPtr::SIZE) == 0;
}
Now my question is, if this is portable. I would be even more happy with a more straightforward way of doing this. I looked in to std::mem_fn, but it seems that the type of these objects is unspecified (the examples on cppreference.com use auto), so I don't think this is where the solution lies.

Is there a way to shorten the C++11 lambda signature in declaration?

I want to shorten the following type of lambdas:
[] (SomeVeryLongTemplateType<int, float, char, std::string>, AnotherLongType) {};
Since the only reason for this lambda is to initialize some class std::function<...> member - it doesn't capture anything, it doesn't have argument names, it returns nothing, it does nothing.
If the shortening operation is expressed as a function of the number of arguments in signature, then I want this function to have the complexity O(1).
Is there a way to do that?
Looks like you're looking for an empty lambda which does nothing, so that your std::function object will always be in callable state!
If so, then use this one which can be reused, for any number of parameters:
static const struct empty_lambda_t //static and const applies to the object!
{
template<typename ...T>
void operator()(T && ... ) const {} //does nothing
}empty_lambda {}; //declare an object which is static and const
And then use it as:
std::function<void()> fun1 = empty_lambda;
std::function<void(int,int)> fun2 = empty_lambda;
std::function<void(whatever)> fun3 = empty_lambda;
Hope that helps.
in C++14 there will be "generic lambdas" that should simplify long type names in parameters as I understand:
auto lambda = [](auto x, auto y) {return x + y; };
here auto is like Template type
http://en.wikipedia.org/wiki/C%2B%2B14#Generic_lambdas
You're looking for "polymorphic lambdas". They do not exist (yet), so no.
However, you can make it easier with proper use of typedefs, so you don't have to type the entire thing every single time.

Returning a priority_queue with custom comparator

I have a function that needs to return a sorted list based on some input parameters. I've selected a std::priority_queue to hold this list.
But the compiler is giving me an error I don't recognize. Here's the code I have:
struct DepthCompare {
bool operator()
(const struct inst *&lhs, const struct inst *&rhs) const
{
return lhs->depth < rhs->depth;
}
};
typedef priority_queue<struct inst*> HeuristicList;
HeuristicList getHeuristicList(struct BasicBlock &) {
HeuristicList ret( DepthCompare );
return ret;
}
The compiler says that a conversion from 'HeuristicList (*)(DepthCompare)' to non-scalar type 'HeuristicList' requested on the return statement's line.
It doesn't look like I'm trying to return a pointer. What's going wrong?
You have two problems.
To use a custom comparator, you must specify the comparator type as the third template argument:
typedef priority_queue<inst*, vector<inst*>, DepthCompare> HeuristicList;
HeuristicList ret( DepthCompare ); is interpreted as a function declaration, rather than a variable declaration, giving the error that you're seeing. You need to pass an instance of the comparator, and make sure it can't be interpreted as a function declaration:
HeuristicList ret = HeuristicList(DepthCompare());
However, since the constuctor's first argument is optional, and defaults to a default-constructed comparator, you can simply write
HeuristicList ret;
Or, since you're just returning the variable straight away,
return HeuristicList();
Note that the comparator is the third template parameter of priority_queue. You must declare your priority_queue like such:
typedef priority_queue<inst*, vector<inst*>, DepthCompare> HeuristicList;
This assumes you want to use vector as the backing container (default).
Also note that in your comparator functor, you want to declare the parameters as const reference to a pointer. What you have is a reference to a pointer to const. You want this:
bool operator()(inst* const& lhs, inst* const& rhs) const
You also don't need to pass an instance of your comparator object to the priority_queue constructor, as the default comparator constructor will do just fine.