I have been trying to create this class which can either use the default functor as an argument or the user can provide one if he wants. But I am unable to pass function pointer as my template argument. Can you please help me in understanding what I am missing.
template <typename T>
struct CheckFunctor
{
bool operator()(T obj)
{
return true;
}
};
template <typename _Ty,
class _Pr = CheckFunctor<_Ty>
>
class MyClass
{
typedef _Ty mapped_type;
typedef _Pr CanBeCleaned_type;
_Ty data;
CanBeCleaned_type predicate;
public:
void SomeMethod()
{
if( predicate(data))
{
std::cout << "Do something";
}
}
MyClass(_Ty timeOutDuration, _Pr pred = _Pr())
: data( timeOutDuration), predicate( pred)
{}
};
template< typename T>
struct CheckEvenFunctor
{
bool operator()(T val)
{
return (val%2 == 0);
}
};
bool CheckEven( int val)
{
return (val%2 == 0);
}
int main()
{
//Usage -1
MyClass<int> obj1( 5);
//Usage- 2
MyClass< int, CheckEven> obj2(6, CheckEven); //Error: 'CheckEven' is not a valid template type argument for parameter '_Pr'
//Usage -3
MyClass<int, CheckEvenFunctor<int>>( 7);
}
You are trying to pass CheckEven as a type parameter even though CheckEven is not a type but a function (of type bool(int)). You should define the type as a pointer to the type of function that you are passing. decltype is handy here:
MyClass< int, decltype(&CheckEven)> obj2(6, CheckEven);
You can also create a factory function and let the compiler deduce the template parameters:
template<class T, class F>
MyClass<T, F> makeClass(T timeOutDuration, F pred) {
return {timeOutDuration, pred};
}
auto obj2 = makeClass(6, CheckEven);
It is possible to allow a template parameter to be a function, but your MyClass is expecting the second argument to be a type, not a function. You might think that template specialization could be used to allow you to define MyClass to also take a function in the second template argument, but it won't work. Template specialization allows you to modify the behavior of MyClass for particular types that are passed as template arguments, but those types must still match the template definition of MyClass, which is that the two arguments are types.
You could modify the type of MyClass you are instantiating by making the second argument a function pointer type as suggested in a different answer, but you would lose the advantage of template expansion making your calls to functions inline. Another solution would be to create a helper class that will convert your function into a functor, and use that to create your MyClass instance.
template <bool P (int)>
struct F {
bool operator()(int obj) { return P(obj); }
};
//...
MyClass<int, F<CheckEven> > obj2(6);
Related
Is there a way to determine a return type of a member function pointer?
Code sample:
///// my library
void my_func(auto mptr) { // have to use `auto`
// some logic based on a return type of mptr: int, string, A, etc.
}
///// client code
struct A {
int foo();
std::string bar(int);
};
class B{
public:
A func(int, double);
};
// ... and many other classes
my_func(&A::foo);
my_func(&A::bar);
my_func(&B::func);
// ... many other calls of my_func()
I need to "fill in" my_func().
Edit:
I can't use std::result_of/std::invoke_result as I don't know the full list of parameters of mptr. It's not important with which params a method is supposed to be called as I'm not calling it. I would like to avoid creating an object of base class of mptr even if I'm able to determine it (using declval is ok).
You can use partial template specialization to determine the return type of mptr:
template <typename T>
struct ReturnType;
template <typename Object, typename Return, typename... Args>
struct ReturnType<Return (Object::*)(Args...)>
{
using Type = Return;
};
void my_func(auto mptr) {
typename ReturnType<decltype(mptr)>::Type obj;
}
Live Demo
You can write a function that deduces the type of a member function pointer, and returns the deduced return type. Note that only a declaration, and no definition is needed
template <typename C, typename Ret, typename... Args>
auto ret_type(Ret (C::*)(Args...)) -> Ret;
void my_func(auto mptr)
{
using type = decltype(ret_type(mptr));
}
In my opinion, this is also easier to read than the specialization solution.
Here's a demo
You can also account for cv-qualifiers by adding overloads. e.g.
template <typename C, typename Ret, typename... Args>
auto ret_type(Ret (C::*)(Args...) const) -> Ret;
Here's a demo
I am writing a kind of container class, for which I would like to offer an apply method which evaluates a function on the content of the container.
template<typename T>
struct Foo
{
T val;
/** apply a free function */
template<typename U> Foo<U> apply(U(*fun)(const T&))
{
return Foo<U>(fun(val));
}
/** apply a member function */
template<typename U> Foo<U> apply(U (T::*fun)() const)
{
return Foo<U>((val.*fun)());
}
};
struct Bar{};
template class Foo<Bar>; // this compiles
//template class Foo<int>; // this produces an error
The last line yields error: creating pointer to member function of non-class type ‘const int’. Even though I only instantiated Foo and not used apply at all. So my question is: How can I effectively remove the second overload whenever T is a non-class type?
Note: I also tried having only one overload taking a std::function<U(const T&)>. This kinda works, because both function-pointers and member-function-pointers can be converted to std::function, but this approach effectively disables template deduction for U which makes user-code less readable.
Using std::invoke instead helps, it is much easier to implement and read
template<typename T>
struct Foo
{
T val;
template<typename U> auto apply(U&& fun)
{
return Foo<std::invoke_result_t<U, T>>{std::invoke(std::forward<U>(fun), val)};
}
};
struct Bar{};
template class Foo<Bar>;
template class Foo<int>;
However, this won't compile if the functions are overloaded
int f();
double f(const Bar&);
Foo<Bar>{}.apply(f); // Doesn't compile
The way around that is to use functors instead
Foo<Bar>{}.apply([](auto&& bar) -> decltype(auto) { return f(decltype(bar)(bar)); });
Which also makes it more consistent with member function calls
Foo<Bar>{}.apply([](auto&& bar) -> decltype(auto) { return decltype(bar)(bar).f(); });
In order to remove the second overload you'd need to make it a template and let SFINAE work, e. g. like this:
template<typename T>
struct Foo
{
T val;
//...
/** apply a member function */
template<typename U, typename ObjT>
Foo<U> apply(U (ObjT::*fun)() const)
{
return Foo<U>((val.*fun)());
}
};
Alternatively, you could remove the second overload altogether, and use lambda or std::bind:
#include <functional> // for std::bind
template<typename T>
struct Foo
{
T val;
/** apply a member function */
template<typename U, typename FuncT>
Foo<U> apply(FuncT&& f)
{
return {f(val)};
}
};
struct SomeType
{
int getFive() { return 5; }
};
int main()
{
Foo<SomeType> obj;
obj.apply<int>(std::bind(&SomeType::getFive, std::placeholders::_1));
obj.apply<int>([](SomeType& obj) { return obj.getFive(); });
}
How can I effectively remove the second overload whenever T is a non-class type?
If you can use at least C++11 (and if you tried std::function I suppose you can use it), you can use SFINAE with std::enable_if
template <typename U, typename V>
typename std::enable_if<std::is_class<V>{}
&& std::is_same<V, T>{}, Foo<U>>::type
apply(U (V::*fun)() const)
{ return Foo<U>((val.*fun)()); }
to impose that T is a class.
Observe that you can't check directly T, that is a template parameter of the class, but you have to pass through a V type, a template type of the specific method.
But you can also impose that T and V are the same type (&& std::is_same<V, T>{}).
I'm writing a C++ template that needs two params: typename T, and an arbitrary function that maps T to an unsigned int.
How can I declare and use a template that can do that? I'd like to keep it simple, so that any dumb function can be used.
UPDATE:
Here is an example of what I'd like to do:
template<typename T, function f> // f has signature: unsigned int f(T);
class SortedContainer {
...
}
And, in this file:
unsigned int weight(Package p) { return p.w; }
SortedContainer<Package, &weight> sc;
UPDATE upon writing code
Based on the answers, I tried writing code, but it won't compile. Or rather, the template will compile, but not the test which invokes it.
The template code looks like this:
template<typename T, typename f>
class C {
...f(T)...
...
The invocation code looks like:
struct S {
int operator()(const int n) {
return n; // Dummy test code
}
};
...C<int, S>&...
The error message is:
error: no matching function for call to 'S::S(const int&)'
note: candidates are:
note: S::S()
It seems like it's trying to use S's constructor for some reason, as opposed to using the operator() which I want it to do.
The purpose of the f parameter is that the SortedContainer needs to be able to position T by an integer value. T is not necessarily an integer or even Comparable, so the caller, when instantiating a SortedContainer, needs to pass not only type T, but a function f to transform T to an integer.
The common way of doing this is to accept a general type F for the function. This will allow any kind of function-like object, whether it is a function pointer or a class object with an overloaded operator(). So:
template<class T, class F>
class SortedContainer {
// ...
}
Compare with things like std::map which does exactly this.
The disadvantage of this is that you cannot control what the prototype of the function is. This may or may not be a problem. One way is just to use it as if it was T-to-unsigned int and rely on the fact that the type system will catch any errors at the point of use.
Another way would be to verify the constraint with some kind of type trait. An example:
static_assert(std::is_same<unsigned int,
typename std::result_of<F(T)>::type>::value,
"Function must be T-to-unsigned int");
Edit: I wrote a small example to convince myself i got the assert right, might as well post it. Here, using A will compile OK but B will fail the assertion.
#include <type_traits>
template<class T, class F>
class SortedContainer {
static_assert(std::is_same<unsigned int,
typename std::result_of<F(T)>::type>::value,
"Function must be T-to-unsigned int");
};
struct A {
unsigned int operator()(double) { return 0; }
};
struct B {
double operator()(double) { return 0; }
};
int main() {
SortedContainer<double, A> a;
SortedContainer<double, B> b;
}
Based on your other edit:
Note that the templated type F only captures the type of the function. You still need an object of this type - the actual function - to call. Again, compare with std::map which first is templated to take a comparator type, and then has a constructor that takes an object of this type. This is true even if you use a normal function - the type will be SortedContainer<T, unsigned int (*)(T)>, but you would somehow need to pass the actual function pointer into the container (probably through the constructor).
Something like this:
template<class T, class F>
class SortedContainer {
public:
SortedContainer(F f = F()): func(f) {}
void foo() {
// ...
func();
// ...
}
private:
F func;
};
struct A {
unsigned int operator()() { return 0; }
};
int main() {
A a;
SortedContainer<double, A> c(a);
c.foo();
}
IMO, you don't require a separate template argument for Function F.
template<typename T> // F not required!
class SortedContainer {
...
};
Choose a good name and use that function by overloading it for various cases. e.g. to_uint()
Since you want to map (i.e. relate) a type to an unsigned int (uint), use following function in global scope:
template<typename T>
uint to_uint (const T& t) {
return t.to_uint(); // Must have `uint to_uint() const` member, else error
}
// Overloads of `to_uint()` for PODs (if needed)
template<typename T> // For all kinds of pointers
uint to_uint (const T* const pT) {
if(pT == nullptr)
<error handling>;
return to_uint(*pT);
}
Scenario: For Sorted_Container<X>, whenever to_uint(x) is invoked, then:
If X is a class, then it must have uint to_uint() const method
Else if X is a POD, then you may have to overload to_uint() for that type
Else, the compiler will generate an error
It's as you said, pretty much:
template< typename T, unsigned int f(T) >
struct SortedContainer;
...
SortedContainer<Package, weight> sc;
if you actually wanted the argument to be a function pointer rather than a function,
template< typename T, unsigned int (*f)(T) >
and similarly if you want the argument to be a function reference.
(naturally, this will only work for dumb functions, not for function objects with an operator() operator of the right signature)
You may use C-style function pointers as #Hurkyl suggests, or std::function which probably can't be template parameters, but I think that idea is wrong.
C++ templates are duck-typed, so STL code in many places (std::unordered_map -> std::hash, std::sort -> std::less) relies on that. I think you should also apply this approach - just ask user to provide specialization for type T:
/* Universal implementation */
template<typename T>
unsigned int sorted_container_weight(T t) { return t; }
template<typename T>
class SortedContainer {
T t;
public:
unsigned int somefunc() {
return sorted_container_weight(t);
}
};
template<>
unsigned int sorted_container_weight<Package>(Package p) { return p.w; }
SortedContainer<Package> sc;
Suppose I have a simple template class:
template <typename ElementType, ElementType Element>
class ConsecutiveMatcher
{
public:
bool operator () (ElementType lhs, ElementType rhs)
{
return lhs == Element && rhs == Element;
}
};
I would usually make instantiation simpler than ConsecutiveMatcher<wchar_t, L'\\'>() by providing a function which can infer the template argument types based on the parameter types:
template <typename ElementType>
ConsecutiveMatcher<ElementType, Element /* ?? */>
MakeConsMatcher(ElementType Element)
{
return ConsecutiveMatcher<ElementType, Element>();
}
However, in this case, MakeConsMatcher(L'\\') will not work, because the function needs to return a class whose template does not only contain a type, but also a value.
How can I return a class template from a function which has not only type template arguments, but also value template arguments?
You want a runtime computed value turned into an template argument? it's not possible.
I'm just looking for a way to omit the wchar_t and use automatic type deduction during instantiation.
I can imagine such situations:
Argument type only known at runtime (and you have no any idea about it): you cannot handle it with templates: you will want to redesign your code and use inheritance and virtual functions (or, probably, mix both, templates and inheritance)
Argument type known at compile-time, argument value known at runtime: left Type of argument in template argument list and pass argument value to constructor, then, for user's convenience, make factory function to deduce type
template<typename T>
struct MyType
{
template <class T>
MyType(const T& defaultValue) :
value(defaultValue)
{}
T value;
};
template<typename T>
MyType<T> MyFactory(const T& defaultValue)
{
return MyType<T>(defaultValue);
}
int main()
{
char c = 'a';
wchar_t w = L'a';
int i = 42;
float f = 3.14f;
auto mt_char = MyFactory(c);
auto mt_wchar = MyFactory(w);
auto mt_int = MyFactory(i);
auto mt_float = MyFactory(f);
}
At compile-time you know a list of Types and want they behave differently (for example have different default values): make template specializations for each type from a list, then, for user's convenience, create typedefs
template<typename T> struct MyType
{
MyType(const T& defaultValue) :
value(defaultValue)
{}
T value;
};
template<>
struct MyType <char>
{
MyType() :
value('c')
{}
char value;
};
template<>
struct MyType <wchar_t>
{
MyType() :
value(L'w')
{}
wchar_t value;
};
typedef MyType<char> MyTypeChar;
typedef MyType<wchar_t> MyTypeWchar;
int main()
{
MyTypeChar mt_char_default;
MyTypeWchar mt_wchar_default;
}
In this case, user still can instantiate own specializations. Example of that approach is a std::basic_string class.
Further, you can simplify your specializations, if make class members static or static const and for integral types just define in member list:
template<>
struct MyType <char>
{
static const char value = 'c';
};
Here I have functor of the follow kind:
template<class T, class Foo, T Foo::*p>
struct X {
void operator()(Foo & f) {
(f.*p) = 12 * (f.*p); // simple example. could be more complex `operator()`
}
};
And sample struct:
struct FF
{
int m;
int r;
};
I want to use the functor X, but I don't want to explicitly specify template argument as follows:
void testforx()
{
std::vector<FF> cont(5);
std::for_each(cont.begin(), cont.end(), X<int, FF, &FF::r>() ); // it work, but I don't want to write `int` and `FF`
std::for_each(cont.begin(), cont.end(), createx<&FF::r>() ); // how I would like to use it, how to declare `createx` function?
}
Here what I tried with no success:
// that is what I tried, but it could not deduce T and Foo
template<T Foo::*p, class T, class Foo>
X<T, Foo, T Foo::*p> createx()
{
return X<T, Foo, p>();
}
// this works, but requires to write T and Foo explicitly
template<class T, class Foo, T Foo::*p>
X<T, Foo, T Foo::*p> createx()
{
return X<T, Foo, p>();
}
I just wouldn't store the member pointer as a template argument:
template<class T, class Foo>
struct X {
X(T Foo::*p): p(p) {}
void operator()(Foo & f) {
(f.*p) = 12 * (f.*p); // simple example. could be more complex `operator()`
}
private:
T Foo::*p;
};
template <class T, class Foo>
X<T, Foo> MakeX(T Foo::*p)
{
return p;
}
I don't think it is possible to deduce the types with your approach: you can't use a pointer-to-member passed to a function which is where the type deduction occurs.
Edit:
There may be macro-based solutions, though.
For example, you can make a class to create X instances, like this:
template <class T, class Foo>
struct XMaker
{
template <T Foo::*p>
X<T, Foo, p> make() { return X<T, Foo, p>(); }
};
Now, you can create a make... function to deduce T and Foo:
template <class T, class Foo>
XMaker<T, Foo> make_x_maker(T Foo::*)
{
return XMaker<T, Foo>();
}
Which makes it possible to write a macro like:
#define CREATE_X(member) make_x_maker(member).make<member>()
Usage:
std::for_each(cont.begin(), cont.end(), CREATE_X(&FF::r) );
I don't think it's possible to reduce the number of template arguments you have to specify if you want an arbitraty member function pointer to be a template argument.
Instead of member function pointers you could use a normal type parameter for a functor that extracts a reference:
template<typename Func>
class X
{
public:
explicit X(Func f = Func()) : f(f) {}
template<class K>
void operator()(K & k) const {
f(k) = 12 * f(k);
}
private:
Func f;
};
Then, you still have the option to use a special functor that directly accesses a certain member (if you think this provides better performance), or use a more general accessor functor that does so with a member function pointer as a member.
I would have one question: do you really need to specify all those arguments ?
struct XR
{
template <class Foo>
void operator()(Foo& foo) const { foo.r = 12 * foo.r; }
};
This works, there is no need for an extra make method it just works:
void testforx()
{
std::vector<FF> cont(5);
std::for_each(cont.begin(), cont.end(), XR());
}
I prefer not to be TOO generic when I create templates.
If you need to have a more complex operator(), you can always do some heavy lifting INSIDE it.
Also, you may consider Boost.Bind, if you really wish to extract pointer functions and references to attributes.
EDIT:
I have an idea, that will be a bit different and does not involve any macro magic, nor even any metaprogramming magic.
Why not simply use a typedef and be done with it ?
Okay, may be not as automated as you wish... but you have only to type this once, after all.
typedef X<int,FF,&FF::m> X_FF_m; // once
std::for_each(cont.begin(), cont.end(), X_FF_m() );
Seems less typing than
std::for_each(cont.begin(), cont.end(), createX<&FF::m>());
repeated over and over.
I barely use naked templates in my code, I prefer to typedef them to improve readability.