C++ function pointer as template - c++

I just started on C++ so sorry if this is a newbie-ish question. I searched all over the web and didn't find anything about this. In fact I wasn't even sure how to formulate my search...
I saw this code somewhere:
template <class T>
struct SomeStruct
{
SomeStruct() {}
};
And later, this:
int main()
{
SomeStruct<void (Foo::*)(int test)> mStruct;
}
The above compiles just fine.
So if I understood it correctly, "void (Foo::*)(int test)" is a function pointer that points to some function in Foo taking a int as argument and returning void.
How can that be a legal argument for the "class T" parameter?
Any help would be appreciated.

void (Foo::*)(int test) is a type of pointer to member function. A variable of such type can be used to point to member function of class Foo (that returns void and takes a single int argument).
class T is a misnomer there - arbitrary type can be used as a template parameter (the type doesn't have to be declared as class), regardless if the template is declared with template<class T> or template<typename T>.
For this reason I don't use the first form, only the latter.
In context of template parameter list of template declaration, typename and class can be used interchangeably, except you must use class in template template parameters (like template<template<typename, typename> class> before C++1z.

It's a function pointer type. Perfectly legitimate.
The argument doesn't have to be an actual class; the use of class there is misleading, and is equivalent to the clearer typename.
If you want to really be freaked out, look up non-type template arguments, because you can in fact pass an actual function pointer (with a little modification). :)

Related

Can C++11 deduce class type and member type from pointer-to-member template parameter

I'd like to make a traits class to deduce the class and member types
from the pointer to a class member -- a single template parameter.
e.g.
given
struct Example { int val; };
, I want a class
pointer_member<&Example::val>
with type definitions class_type=Example, member_type=int and the pointer-to-member itself.
I know c++17 can do this with template <auto>, but I'm stuck with c++11.
I know I could explicitly specify the class and member typenames preceding the pointer-to-member parameter. I hate redundancy. The compiler should know everything from &Example::val.
I know I could create a template function having template parameters <typename class_type,typename member_type> deduced by calling with a function argument member_type class_type::*ptr_to_mem. I'd even be willing to use the decltype() of such a call. Unfortunately, I need to access the specific member ptr_to_mem as a template parameter, not (just) as a passed argument. I cannot see how.
The Motivation and Scope of P0127r1 suggest this is not possible with C++11.
ManuelAtWorks' answer appears the best option for C++11.
In c++17, template <auto value> which allows pointer_member<&Example::val> usage.
For previous version, there are workaround, such as template <typename T, T value> with usage changed to pointer_member<decltype(&Example::val), &Example::val>
MACRO can simplify usage a little:
#define AUTO(value) decltype(value), value
and then
pointer_member<AUTO(&Example::val)>

Why is function call treated as instantiation when I cast in template arguments?

I've got the following code:
template <bool condition>
struct enable_if { };
template <>
struct enable_if<true> { using type = bool; };
template <typename T>
class is_callable {
using Yes = char[1];
using No = char[2];
template <typename U> static Yes& filter(decltype(&U::operator()));
template <typename U> static No& filter(...);
public:
constexpr operator bool() { return sizeof(filter<T>(nullptr)) == sizeof(Yes); }
};
template <typename Lambda, typename enable_if<is_callable<Lambda>{}>::type = true>
void doSomethingWithLambda(Lambda func) {
func();
}
int main() {
doSomethingWithLambda([]() { });
}
The important part is the enable_if<is_callable<Lambda>{}>::type part.
One is forced to instantiate is_callable<Lambda> with {} because if one were to use (), C++ would mistake it for a function call.
Feel free to correct me if I'm wrong, but as far as I know, C++ assumes it is a function in the () case so that the type of expression isn't determined after the time of writing, saving everyone a headache. What I mean by that is, assuming you had a function version and a class version of is_callable (separated by SFINAE using enable_if or something along those lines), the type Lambda could determine the true meaning of (), either a function call or an instantiation. Like I said, as far as I know, C++ wants to avoid this confusion, so it assumes function call and fails if such a function does not exist.
Based on the assumptions above, the following shouldn't work:
enable_if<(bool)is_callable<Lambda>()>::type
What does it matter if I cast the result of the function call (never mind that functions couldn't even be evaluated in this context)? Why is this suddenly treated as an instantiation instead of a function call?
No, your understanding is not correct.
Firstly, a name can't refer to both a class template and a function template. If that happens the program is ill-formed. (And defining both in the same scope is not allowed to begin with.)
Secondly, is_callable<Lambda>() as template argument is not a function call to begin with. It is a function type. It is the type of a function which has no parameters and returns a is_callable<Lambda>.
When the compiler parses a template argument, it can interpret it in two ways: Either as a type or as an expression (or as a braced-init-list), because template parameters can be type parameters or non-type parameters.
When the compiler reads is_callable<Lambda>() it notices that is_callable is a class template and then realizes that is_callable<Lambda> is therefore a type. If you have a type, let's shorten it to T, then T() can either be syntax representing the type of a function returning T and taking no arguments, or it can be an expression formed from one single functional notation explicit cast (which you imprecisely call "instantiation").
There is no way to differentiate these two cases in the context, but the compiler needs to know whether this is a type template argument or a non-type template argument. So there is a rule saying that such ambiguities are always resolved in favor of a type.
If is_callable was a function template instead, there would be no ambiguity, because then is_callable<Lambda> is not a type and therefore is_callable<Lambda>() cannot be a function type. It must be a function call instead and therefore an expression and non-type template argument.
When you write (bool)is_callable<Lambda>() this is not valid syntax for a type and therefore there is no ambiguity. It is a non-type template argument and an expression. And is_callable<Lambda>() is a funcational notation explicit cast because is_callable<Lambbda> is a type. If is_callable was a function template instead of a class template, then it would be a function call.

Understanding this highly templated C++ function binder

template<typename Container, typename Ret, typename ...Args>
struct BindImpl {
template<Ret (Container::*MemberFunc)(Args...)>
class Callable {
public:
inline constexpr Callable (Container *container) :
m_container(container)
{}
inline Ret operator() (Args ...args) const
{
return (m_container->*MemberFunc)(std::forward<Args>(args)...);
}
inline Function<Ret(Args...)> toFunction() const
{
return Function<Ret(Args...)>(*this);
}
private:
Container *m_container;
};
};
template<typename Container, typename Ret, typename ...Args>
BindImpl<Container, Ret, Args...> DeduceImpl (Ret (Container::*)(Args...));
This code is called like this:
(typename decltype(::AIpStack::BindPrivate::DeduceImpl(&EthIpIface::driverSendIp4Packet)) ::template Callable<&EthIpIface::driverSendIp4Packet>((this)).toFunction())
I'm trying to understand what this code does. It apprently is a way to bind function pointers (like &EthIpIface::driverSendIp4Packet) to something.
The line above is from this macro, which fills this struct member, if anyone is intersted. You may wanna have a loot at Function.
The first part that I don't understand is
template<Ret (Container::*MemberFunc)(Args...)>
For me a template must be followed by typename. Also, what follows typename, is the thing to be substituted for. I don't see how this template makes Callable templated. I don't know where something goes to in Callable<something>.
Also, what is DeduceImpl? Looks like a function declaration but without a definition.
Also, what Container::*MemberFunc means?
Firstly, templates can also take in non-type parameters as well as with typename and class. In this case:
template<Ret (Container::*MemberFunc)(Args...)>
This is a template taking a function pointer as a parameter, where Ret is the return type, Container::*MemberFunc is the pointer to a specific member function in Container with Args... referencing variadic arguments. This gives the pointer the identifier MemberFunc. I have a feeling the asterisk following the scope resolution operator confused you, as usually you would receive a compiler error if you used these two together in any other situation but in this specific case these two are considered one token ::* representing this kind of template parameter instead of the two :: and *.
For this line:
BindImpl<Container, Ret, Args...> DeduceImpl (Ret (Container::*)(Args...));
It is a function declaration. This is a function named DeduceImpl that will return a BindImpl struct that takes a function pointer as an argument. I'm inferring that this function is the interface by which you bind the function pointer, hence the (probably) shortened names "Deduce Implementation" and "Bind Implementation" From what I've read, this function is only used for decltype, so there's no actual definition for this function.
For how this template is actually being utilized in this line (reformatted for easier reading):
typename decltype(::AIpStack::BindPrivate::DeduceImpl(&EthIpIface::driverSendIp4Packet))
::
template Callable<&EthIpIface::driverSendIp4Packet>(this).toFunction()
This is a template disambiguator created just so the compiler knows that the actual template is being utilized instead of a less-than comparison operator.
You wouldn't write all of this just to use the template. This line was probably written because it's one of the few ways the template is instantiated in the project.
In summary:
template<Ret (Container::*MemberFunc)(Args...)> is a template that takes a function pointer referred to as MemberFunc as a parameter.
DeduceImpl returns a BindImpl struct by taking in the function pointer you want to bind.

c++ is_member_pointer implementation

In c++ std library, is_member_pointer is implemented as
template<typename _Tp>
struct __is_member_pointer_helper
: public false_type { };
template<typename _Tp, typename _Cp>
struct __is_member_pointer_helper<_Tp _Cp::*>
: public true_type { };
/// is_member_pointer
template<typename _Tp>
struct is_member_pointer
: public __is_member_pointer_helper<typename remove_cv<_Tp>::type>::type
{ };
Can someone explain that how the _Cp is deduced? It works like a magic.
The type of a pointer-to-member is Type Class::*, where Type is the object type or function type being pointed to. If you provide the template an int C::*, for example, the compiler can simply deduce the class type by examining the type of the pointer-to-member and seeing the class type is C. It would also deduce the pointed-to type as int the same way. It works very similarly to how we humans would do it. In general, we call this technique pattern matching, which you might be familiar with from regular expressions.
Formally:
[temp.deduct.type]/3.2:
A pointer-to-member type includes the type of the class object pointed to and the type of the member pointed to.
[temp.deduct.type]/8:
A template type argument T, a template template argument TT or a template non-type argument i can be deduced if P and A have one of the following forms:
[snip]
T T::*
[snip]
Where per [temp.deduct.type]/1:
Template arguments can be deduced in several different contexts, but in each case a type that is specified in terms of template parameters (call it P) is compared with an actual type (call it A), and an attempt is made to find template argument values (a type for a type parameter, a value for a non-type parameter, or a template for a template parameter) that will make P, after substitution of the deduced values (call it the deduced A), compatible with A.
Some years ago I basically had the same misunderstanding about C++ template specialization that, apparently, you are having now.
The other answers are great, but I don't think they would have really helped me back then understanding what's going on. So, assuming that you are suffering from the same misunderstanding that I did, let me try to explain how I finally got my thoughts right:
Back then, my intuitive understanding erroneously told me that the term "specialization" means that the "specialized template" should somehow have less template arguments than the "original template". This assumption was driven by the fact that almost every tutorial code that tries to explain how specialization works starts with an example like
template <class T> // <-- one parameter
class MyClass { ... };
template <> // <-- zero parameters
class MyClass<int> { ... };
Now, your example of is_member_pointer is one counterexample showing that this is not true at all.
My entire misunderstanding started with using wrong terminology. You may have noticed that above I put quotes around "specialized template" and "original template"? I did this because it's wrong, but those were the words that I was using back then.
True is, that there is only one template. It's wrong to say that there are two templates, an original one and a specialized one. In my example
template <class T>
class MyClass { ... };
is the template, while
template <>
class MyClass<int> { ... };
is a specialization of that same template.
What makes it a specialization, is the use of <int> behind the class name. That's it!
This is another valid specialization of that same template:
template <class... Types>
struct many_to_one { ... };
template <class A, class B, class C, class D> // <-- four parameters, could be even more
class MyClass<many_to_one<A, B, C, D>> { ... };
As you can see, the specialization has way more template parameters than the actual template. And that's perfectly valid as long as the number of specialization types (one type in this example, namely many_to_one<A, B, C, D>) matches the number of template parameters of the actual template.
Now, what does the compiler do, if you use MyClass<int> anywhere, e.g. for declaring a variable of that type?
It has a look at the template and all specializations of it.
First thing to note: As in this example there is only one template parameter, something like MyClass<int, double, short, float> cannot compile, even though there is a specialization with four parameters! But those four parameters apply to the specialization, not to the template.
When the compiler walks through all the specializations and it finds
template <class A, class B, class C, class D>
class MyClass<many_to_one<A, B, C, D>> { ... };
it has to ask itself "are there any types A, B, C, D so that the given type (int) is equal to the specialization type many_to_one<A, B, C, D>? The answer is No, so it moves on to the next specialization:
template <>
class MyClass<int> { ... };
Again, it asks itself "are there any types <empty list here> so that the given type (int) is equal to the specialization type int? Obviously, yes! Since there are no even better matching specializations, it chooses this one.
If instead you have e.g. MyClass<double>, both questions for the two specializations yield No as the answer, so the "basic" template will be chosen.
So, to finally answer your original question: If you write e.g.
std::is_member_pointer<decltype(&std::string::size)>
the compiler looks at the specialization and sees "Oh, look. If I put _Tp = size_t and _Cp = std::string then the given type decltype(&std::string::size) is equal to the specialization type _Tp _Cp::*, so I pick that specialization (that happens to inherit from std::true_type)".
But if you write e.g.
std::is_member_pointer<int>
then it cannot find any types for _Tp and _Cp to make _Tp _Cp::* equal to int, so it discards that specialization and chooses the "basic" template (that happens to inherit from std::false_type).
There is nothing magical about it. It is simple specialization, and _Cp is deduced to containing class, whenever the template is instantiated for the class member.
It is an application of general case of selecting best available specialization.

Why c++ template parameters should be declared as class type?

Syntax of Function Template
template <**class** T, ...>
returntype functionname(arguments)
{
.....
.....
}
I have two Questions?
Why the template parameter should be declared as a class type?(ie
with the use of class keyword)
When we declared it as a class type then what the thing the compiler
will do?
That's the usual confusion that arises from the usage of class in template arguments.
That class thing has nothing to do with classes; it merely says that the template accepts a type template argument (as opposed to integral1 template arguments), which can be any type, not only classes.
So, why did they choose class? Because they had to use a keyword that was surely not used in any C++ program and more or less "sounded good" - and class was ok, since it was already a reserved keyword in C++.
Notice that there's an alternative to class: the typename keyword. They are perfectly equivalent2, but typename in my opinion is much more clear, since the name just says "what follows is a type argument", without making you think that it must be a class.
Why both syntax are allowed? Because the typename keyword had do be introduced in the language later (when they noticed that it was necessary to add another keyword to disambiguate some declarations inside templates); then, it was "retrofitted" also for the template arguments declarations. This usage of the class keyword was kept for compatibility with programs/documentation written in the meantime.
here I say "integral" for simplicity, obviously I mean non-type template parameters in general (C++11, §14.1 ¶4).
There is no semantic difference between class and typename in a template-parameter.
(C++11, §14.1 ¶2)
Because that's the word that the language definiton tells you to use. 'class T' in this context means 'T is the name of some type', not 'T is the name of some class'.
I believe the rationale lies in a desire to not add yet another reserved word.
However, the language eventually added yet another reserved word: you can equivalently say 'typename T'.
According to the Standard, there are two keywords : class and typename. You can use any one of them in a template definition. Both has same meaning: when you write class (or typename) in a template definition, it means the user of the template has to pass a type as template argument to the template; it doesn't mean anything more than that. If it is a function template, then the template argument may be deduced (in some cases) from the argument to the function.
Note that you can pass standard types to template, not only classes:
template <class T, int N> class mysequence {..};
So, class keyword here tells the compiler to treat T as class. And N is treated as integer.
(1) Why the template parameter should be declared as a class type?
Not true entirely. You can use typename as well. :)
More importantly, you can declare const object of certain types also as a parameter. e.g.
template<int I> // <---- 'I' is not a class/typename
class A { ... };
...
A<3> obj;
(2) When we declared it as a class type then what the thing the compiler
will do?
Actually not much.
However, compiler checks the type is actually a type-name, when you invoke its objects. e.g.
template<class T>
class A { ... }; // ok ... not much to check
...
A<int> obj1; // compiler checks if 'int' is a type ---> yes
A<3> obj2; // compiler checks if '3' is a type ---> no