Suppose I want to create a functor that acts upon some general type.
For example
template<typename Ape>
class functor1
{
void operator()(Ape& m)
{
// Do something to m
}
};
This has been the standard way of doing things for me. However, I also have another way:
class functor2
{
template<typename Ape>
void operator()(Ape& m)
{
// Do something to m
}
};
The advantage of the second approach is that I don't have to explicitly state the type of the template.
int main()
{
std::vector<chimpanzee> chimps(100);
for_each(chimps.begin(), chimps.end(), functor1<chimpanzee>()); // Explicity state the type
for_each(chimps.begin(), chimps.end(), functor2()); // Less typing. Will it work?
}
Will the second version work? Or am I missing something? If it works are there any advantages to the first approach?
The obvious difference is that in the first case you specify the type explicitly, and in the second case it is the compiler that will deduce the type for you in the context of the actual call. However, in you specific example it might make no real difference at all.
If your class had multiple member functions in it, the first variant would "fix" the same template parameter for all of them, while in the second variant the parameter would be deduced for each member function independently.
The same is true when a single member function is called from multiple contexts: each context will perform its own template argument deduction in the second variant.
It could be good or not so good, depending on your intent.
If your function accepted its argument by value (or by const reference), in the first variant you could specify a different type for the argument than the one stored in the container. For example, you could have created a functor for long and applied it to the container of ints. This is not possible in the second variant.
For example, if your chimpanzee class was polymorphic, derived from animal, you could have used a functor1<animal> to iterate over such container. In the second variant the template parameter will be deduced for you as chimpanzee, not as animal.
If your class had data members, the second variant would make sure that all specializations of member function(s) share the same data, if the same functor object is used. In the first variant each specialization is a different class, it gets its own data.
For functors with no state this should be the same. Frequently (compares) you need to store another object/ref/pointer of the same type in the functor and your second option wouldn't work in that case. Note that if your functor does need constructor parameters you can make a free function make_<foo> like make_pair to deduce the type for you and again reduce typing.
It's like scoping: in functor1, anything in the class can use the type Ape (for member declarations, parameter and return types types, traits, or whatever), while in functor2, Ape only means something within the scope of operator(). In short:
Time of definition:
functor1 needs to know about Ape when it is created.
functor2 doesn't need to know about Ape until it is called.
Scope of type:
Everything in functor1 knows about Ape.
Only operator() in functor2 knows about Ape.
Versatility of an instance:
A functor1 instance only works with a single type of Ape.
A functor2 instance works with any type of Ape.
Related
I was wondering if writing anything resembling this declaration (making use of the parameter pack) is possible.
decltype(auto) (*funcPtr)(...);
If possible, I would also like to know about alternative ways to declare such a pointer.
C++ is a statically typed language. All function argument types and return types must be known at compile time. You cannot declare a function that returns arbitrary types (well, I guess you could return std::any, but I can't think of a case where you'd want to).
You can use templates, however, to create function templates where the compiler will stamp out multiple versions of a function for you, so you don't have to write them all yourself.
Remember that auto and decltype(auto) is not magic. They are just syntactic sugar for what you'd otherwise write yourself if they didn't exist. They do not enable any new features that weren't already in the language. They just make such features easier to use.
No, there is no type such as pointer to function "that returns anything". There are only pointers to a function that returns some type or void. auto merely deduces the type from an initialiser, and there is nothing to deduce the type from in your example.
You can however have a function template where the instance of the template is a function that returns a type specified by a template argument:
// function template
template<class T>
T foo() {
return {};
}
Likewise, you can have a variable template that is a pointer to function whose return type is specified by a template variable:
// variable template
template<class T>
T (*funcPtr)() = foo;
// example usage
int main() {
return funcPtr<int>();
}
I have a class myClass that is templated, and I have it in mind to use it for two particular types.
The trouble is that whether or not something should be const in myClass depends on whether it is instantiated with the first type (in which pretty much everything is const) or the second type (in which pretty much everything is non-const).
How do I solve this problem? It seems there are two possible approaches.
I could write const in the templated code as if it were for the first type (the one that actually is const), and then somehow "throw away" all those consts once I instantiate with the second type? Is this possible?
The second approach is to not write const at all, and then when I instantiate myClass with the first type, I make the entire object itself const. This seems to make up a bit for the lack of const-correctness in the class implementation itself...
Or maybe I can do something else?
EDIT: Wait, no, the last approach wouldn't work, as I then wouldn't be able to call non-const methods....
Let's assume you have these two arbitrary types you want to instantiate your template class with, the first of which should trigger constness for your members:
struct RequiresConst
{};
struct OtherStruct
{};
You can then write some convenience templates like this:
template<class T, bool B>
using conditional_const = typename std::conditional<B, const T, T>::type;
template<class T>
constexpr bool needsConst = std::is_same_v<T, RequiresConst>;
This allows you to naturally spell out what you want:
template<class T>
struct MyClass
{
conditional_const<int, needsConst<T>> member;
};
Demo (including test).
Note that this only works for member variables. I'm not aware of a way to make functions const or non-const in a similarly convenient way. But you could write a const and non-const version for each function and enable exactly one of each pair via std::enable_if (or some other SFINAE).
It should also be mentioned that "this member should be const if the template parameter is this exact class" is a pretty odd requirement - not necessarily wrong but smelly. There is probably some specific trait that class has that you should check instead. But maybe your use case really only ever has the template instantiated for those two classes and the above will be sufficient.
Use a type_traits class.
Start with an empty typetraits class, then specialize it for your first type. Place there all the types you need with the const.
Then specialize it again for your second type, and place there the types without const.
Finally, in your templated class, use the type traits with the template type to select the types you need.
I have been looking at some of the Boost source code and noticed they implement templated functions by using a functor instead of a plain function? Is there a reason for this?
For example:
template<typename Foo, typename Bar>
struct functor {
Bar operator()(const Foo& foo) {
return foo.as_bar();
}
};
as opposed to:
template<typename Foo, typename Bar>
Bar func(const Foo& foo) {
return foo.as_bar();
}
The only advantage I can come up with is it allows classes to inherit the function?
There are two main reasons: The first is, as pythonic metaphor noted, partial specialization is only valid for classes and not functions. Note that functions can use overloads to overcome this problem generally, but often if you are doing metaprogramming it's easier and more generic to use partial specialization. I'd actually think this was the main reason.
The second reason is that anytime that code wants to accept a function object (like in the STL, e.g. std::transform), it will have a type template parameter. If you pass a functor or a lambda, the exact type is known at compile time, and you don't pay for indirection, and inlining can be performed. If you pass a function pointer (or a std::function), only the signature is known at compile time, and you pay for an indirection (and you can't inline). For instance, std::sort can be considerably faster with a functor than a function pointer.
Note that there is a little used feature called function pointer template parameters; these are non type template parameters that specialize on a specific function, and thus can remove indirection. However, if you use one of these, you can't use a functor at all. So most code that wants to accepts a function object does it the way I described above.
Am I able to implement the following function in C++?
I would like to keep the myInstance variable unspecified until the callback method is called, instead of containing it in a boost::bind instance.
MyClass *myInstance;
void call(/* boost::mem_fn */ callback)
{
// Somewhere in this function, the operator()() method
// is called on the callback instance
callback(myInstance);
}
call(boost::mem_fn(&MyClass::myMethod));
I understand that boost::mem_fn is a function which returns a particular object, but I'm unsure of its type. The documentation says unspecified as its return type. One of the boost::bind constructors takes this type as a parameter, but I'm unable to find the actual declaration in its implementation. Also, am I even allowed to store my own instance of this particular type, or is this strictly for use by boost functions?
This is one of those cases where it seems that the compiler is doing some very magic stuff.
The reason there isn't really a well defined type is that the type returned from bosst::mem_fn is always assumed to be a template parameter of the function it's passed to. Let me show you an example:
std::for_each has a signature like this:
template <class InputIterator, class Function>
Function for_each (InputIterator first, InputIterator last, Function f);
This little slice of magic has two template parameters, an InputIterator and a Function. These could have been called anything, but the names given to them describe how they will be used, really, are more self-documenting names than a real type. The type of InputIterator may well be something like std::vector<foo>::iterator - the point is that the compiler will automatically resolve what an "InputIterator" is at compile time. It can figure this type out for you.
The same is true of Function. As long as you pass it something that can be called - that is, has a version of operator() that is compatible with what gets called in for_each, then you never need to know what Function is.
So the short answer is, make your call function take a template parameter:
template<typename SomeSortOfFunction>
void call(SomeSortOfFunction callback)
and then the compiler should resolve SomeSortOfFunction to be whatever the type is that is returned from boost::mem_fn
The return type of boost::mem_fn is unspecified. You should use either Matt's approach (i.e. pass it as a template), or if separate compilation is important to you, use type erasure:
MyClass *myInstance;
void call(boost::function<void(MyClass*)> callback)
{
callback(myInstance);
}
call(boost::mem_fn(&MyClass::myMethod));
The return type of mem_fn is not something you should ever explicitly type or store. It is generated at compile time via the types of the arguments.
It can, however, be stored via std::function (or boost::function).
The operator() signature of men_fn is the original method arguments with a possibly const pointer to the class prepended, and the same return value type. Just create a std::function with that signature, and it can take the men_fn type and store it.
In short if you have a zero argument method for class foo that returns void try storing the men_fun in a std::function<void(foo *)>.
Without knowing a function's type, I am declaring its pointer with below technique and initializing a function pointer.
template<typename T>
struct Declare { typedef T Type; }; // for declaring any func ptr
void fun () {}
int main ()
{
Declare<fun>::Type pf = &fun; // can't use C++0x 'auto'
}
However, it gives compile error as, error: expected a type, got ‘fun’. Though the type of any method is known at compile time. Is it invalid to pass a function into a class template as above ?
[Note: replacing fun with void (*)() works fine. But that's not what want.]
Is it invalid to pass a function into a class template as above ?
Totally yes, you're mixing up type and non-type parameters.
fun is a non-type argument, it's an address of a function, like an arbitary number 0x12345678.
typename T is a type parameter. You can only pass it types, like int,MyClass, double (*)(std::string), void (MyClass::*)().
You'll just have to life with the fact, that you need compiler support for that stuff or some really ugly trickery to deduce the type.
If you're in for the trickery, there's Boost.Typeof for non-C++0x coder like you. It also provides a stand-in for auto with BOOST_AUTO, but that is only a short way for writing BOOST_TYPEOF:
int hello(){ return 42; }
BOOST_AUTO(var1,hello()); // type of var1 == int
BOOST_TYPEOF(hello()) var2 = hello(); // same
The problem? You need to help it for every user-defined type you have. See this Ideone example.
Now, most of the time I don't think you need Boost.Typeof. Why? Because if you use a function, you of course need to know the signature, how would you pass the correct arguments otherwise? Or use the return type in a correct way?
The other times are the usage in templates anyways. If you declare a function pointer like auto fptr = &func, then you have the knowledge, that func exists, aka you know its signature and type. For when you don't know that func exists, you need it passed to you anyways, preferably in a template:
template<class FPtr>
void myfunc(FPtr otherfunc){
// use otherfunc
}
And with a template you have the knowledge of that functions type again.
Is it invalid to pass a function into a class template as above?
Yes. Because what you, in other words, want the compiler to deduce the type parameter for the class template, which simply not possible in C++. Recall that fun itself isn't a type, its a value of type void (*)(). But your class template expects type, not value. That's why it wouldn't work.
Type deduction is possible with functions only, that means even with the constructor of class. So if you write a templated constructor, and then you can write this:
Declare obj(&fun);
Here the type of the function is known as long as you're in constructor, once you exist from it, you lost the information. So what you probably need is : define a class, say, AbstractFunctor (possibly class template) and derived from it defining an another class say template<Fun fun> struct Functor. Then you can create an instance of Functor which can remember the function type forever, and store the instance in AbstractFunctor* as a member data of Declare.
But I think, even in this way, the type cannot be used as Declare::Type or Declare::AbstractFunctor::Type, simply because the type is stored in an instance of the class; only the instance knows the type. So the getting type using syntax like A::Type is out of the question. And you cannot get type using syntax instance.Type either. All you can do is : call the function, using the instance, like a functor.
EDIT:
If you're allowed to use C++0x's other features (excluding auto), then the problem has a trivial solution:
Declare<decltype(&fun)>::Type pf = &fun;
pf(); //call the function
Demo : http://ideone.com/
But then, you don't need even Declare, as you can do this instead:
decltype(&fun) pf = &fun;
pf(); //call the function