Pass functor to constructor - c++

I have a class that basically needs to store a functor given in the constructor, similar to this:
template <class T>
class Foo {
private:
T func;
public:
Foo(T f) : func(f) { }
}
However, to create a new instance of the Foo class, the I can't seem to do this:
Foo foo(std::less<int>());
because T is a class template parameter. I have to use this clunky syntax instead:
Foo<std::less<int>> foo(std::less<int>());
Is there a better way to do this, without writing the type of the functor twice?

Foo is not a class, it is a class template. You have to instantiate it with a template argument in order to create a type.
Concerning your example, you could add a default constructor for functors that are default constructible, like std::less et al.
template <class T>
class Foo {
private:
T func;
public:
Foo() = default; // C++03 would require Foo() {}
Foo(T f) : func(f) { }
};
then
Foo<std::less<int>> foo;
Alternatively, you can provide a function template that takes a functor and returns a Foo<F> object.

You could use a function to deduce the functor type and return the correct Foo flavor:
template <typename T>
Foo<T> make_foo(T t) { return Foo<T>(t); }
but this solution basically needs auto from C++11 to store the return value:
auto f = make_foo(std::less<int>());

Related

Passing unique_ptr<Derived<T>> to a function

I need to pass a unique pointer to a derived template class to a function that takes a unique base template class, like this:
template <typename T>
class Base {};
template <typename T>
class Derived : public Base<T> {};
template <typename T>
void foo(std::unique_ptr<Base<T>>){}
//or
template <typename T>
class MyClass{
public:
MyClass(std::unique_ptr<Base<T>> arg) : _arg(std::move(arg)) {}
private:
std::unique_ptr<Base<T>> _arg;
};
int main()
{
auto b = make_unique<Derived<int>>();
foo(std::move(b));
MyClass mc(std::move(b))
}
Why is this not working and how can I fix it?
I get an error:
'void foo1<T>(std::unique_ptr<Base<T>,std::default_delete<Base<T>>>)': cannot convert argument 1 from 'std::unique_ptr<Derived<int>,std::default_delete<Derived<int>>>' to 'std::unique_ptr<Base<T>,std::default_delete<Base<T>>>'
but it work
auto derived = std::make_unique<Derived<int>>();
std::unique_ptr<Base<int>> base = std::move(derived);
C++ doesn't deduce template arguments in this situation. You can specify <int>, and that will succeed.
foo<int>(std::move(b)); // fine
MyClass<int> mc(std::move(b)); // fine
See it on coliru
You can't have template argument deduction also consider implicit conversions, at least not in most situations. Normally the argument type must match the parameter type exactly for deduction of a template argument to be possible (in this case to deduce T), but std::unique_ptr<Base<int>> and std::unique_ptr<Dervived<int>> are not the same type.
As the other answer suggests you can explicitly specify the template argument instead of trying to have it be deduced.
If you want to automate this without having to add anything to Derived or Base you can however make use of one of the exceptions to the general rule above. If the template parameter is a reference-to or pointer-to base of the argument type, then it may (with certain conditions) still be used for deduction:
// Here an exception to the deduction rules applies
// and `Base<T>*` can be deduced against a pointer `X*`
// if `X` is (uniquely) derived from a `Base<T>`
template<typename T>
auto as_base_ptr(Base<T>* p){
return p;
}
template<typename X>
auto to_base_unique_ptr(std::unique_ptr<X> p) {
using base_type = std::remove_pointer_t<decltype(as_base_ptr(std::declval<X*>()))>;
return std::unique_ptr<base_type>(std::move(p));
}
template <typename T>
void foo(std::unique_ptr<Base<T>>){
}
template <typename X>
void foo(std::unique_ptr<X> p){
foo(to_base_unqiue_ptr(std::move(p)));
}
But even simpler you can ask yourself whether you really need to have the function foo take std::unique_ptr<Base<T>> specifically (e.g. because you need access to T) or whether std::unique_ptr<X> wouldn't already be enough.

Explicit instantiation of template class with templated member functions

With a class defined as follows:
template <typename T>
class A {
private:
T a;
public:
A(T& a) : a_(a) { }
template <typename D>
void Eval(D& arg)
{
// ...
}
};
template A<int>;
I want to explicitly instantiate one instance of the class, and I want this class to have one explicit instantiation of Eval. The intention here is to get a member function pointer that avoids ambiguity:
auto eval_ptr = &A<int>::Eval;
The ambiguity is not coming from anything to do with template instantiation of the class, it's caused by Eval also being a templated function.
&A<int>::Eval does not point to a function, it points to a template. And there is just no such type as a "pointer to a template".
If you want a pointer to A<int>::Eval, you need to specify D as well.
auto eval_ptr = &A<int>::Eval<int>; works just fine for example.
Addendum: Pointers-to-templates do exist in the grammatical sense, but there is no type an object can have to hold one of them. They must be immediately casted/decayed to a specific overload in order to be used, which doesn't come into play here since you want to store it in an auto.
For example: The following is fine because there's clearly only one "version" of Eval that can be meant:
void bar(void (A<int>::*arg)(int&)) {}
void foo() {
bar(&A<int>::Eval);
}
The very simple solution was specifying both template parameters:
template <typename T>
class A
{
private:
T a;
public:
A(T &a) : a_(a) {}
template <typename D>
void Eval(D &arg)
{
arg+=1;
}
};
int main()
{
auto p = &A<int>::Eval<int>;
}

how to call a function in C++11 templates only when its defined

Looking at a simple template scenario like this:
class A {
public:
int work();
};
class B {
public:
int work();
};
class ObjectManager {
public:
static void manage( A& obj );
// manage not defined for class B
};
template<class T>
doStuff( T t ) {
t.work();
....
ObjectManager::manage(t);
};
A a;
B b;
doStuf(a);
doStuff(b);
I am wondering, what is the cleanest way to implement a conditional call to ObjectManager::manage? The template function should determine in compile-time if ObjectManager::manage(T t) is defined for the given T and activate some lines of code only when it is. I guess there are solutions with some more nested template calls, but it would be the best for me just to keep the function in one piece.
Note that currently your class members are all private. They should be made public.
template<class T>
auto call_manage(T* t) -> decltype(ObjectManager::manage(*t)){
return ObjectManager::manage(*t);
}
void call_manage(...) {}
template<class T>
void doStuff( T t ) {
t.work();
//....
call_manage(std::addressof(t)); // smack whoever overloaded unary
// operator & in the head first
}
If the expression ObjectManager::manage(*t) is well-formed, substitution succeeds for the function template, which is always a better match than ..., so it is called. Otherwise, the do-nothing overload is the only viable function.
Demo.
For those who like references:
template<class T>
auto call_manage(T& t) -> decltype(ObjectManager::manage(t)){
return ObjectManager::manage(t);
}
template<class... T>
void call_manage(T&&...) {}
template<class T>
void doStuff( T t ) {
t.work();
//....
call_manage(t);
}
In this case, the single-argument overload is more specialized than the variadic version by the partial ordering rules for function templates, and is selected by overload resolution if both are equally viable. You can also make it take T&& t and call manage(std::forward<T>(t)), for perfect forwarding.
Demo.

C++ template arguments in constructor

Why doesn't this code compile?
template <class T>
class A
{
public:
A(T t) : t_(t) {}
private:
T t_;
};
int main()
{
A a(5.5);
// A<double> a(5.5); // that's what i don't want to do
}
I want template arguments to be implicit.
Like in this example:
template<class T>
T Foo(T t) { return t; }
// usage:
Foo(5.5);
UPDATE: named-constructor idiom isn't acceptable for me. I want to use this class for RAII.
The only way to do so is const A& a = A::MakeA(t), but it's ugly!
Since you have to name the type of a variable (C++03 can't infer the type of a variable), you can only do:
A<double> a(5.5); // that's what i don't want to do
The situation is a little easier when you needn't make a variable of the type, but want to pass it to some other function. In this case, you define an auxiliary "constructor function" (see std::make_pair):
template <class T>
A<T> make_a(T t) { return A<T>(t); }
and then use it like this:
another_function(make_a(1.1));
In C++0x, you will be able to do even
auto a(make_a(5.5));
to define your variable a.
However, inferring A's argument from its constructor is generally impossible, because you can't tell which specializations have the conversion constructor from a given type. Imagine there's a specialization
template <>
struct A<void>
{
A(double);
};

How to reduce template arguments?

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.