What is non overloaded pointer to member and overloaded pointer to member? - c++

I am reading C++ programming language by Bjarne Stroustrup. I came across the statement in templates section.
A template argument can be a constant expression (§C.5), the address of an object or function
with external linkage (§9.2), or a non overloaded pointer to member (§15.5).
What is non overloaded pointer to member? Can someone give example?

A non-overloaded pointer-to-member is as the name states -- a pointer to a member that hasn't overloaded a superclass. Here's an example I've just put together of what will and won't work:
#include <iostream>
class Foo {
public:
virtual void printN() { std::cout << 42; }
};
class Bar : public Foo {
public:
void printN() { std::cout << 31; }
};
template <typename T, typename C>
class SomeTemplate {
public:
void PrintData(T d) { C c; (c.*d)(); }
};
int main() {
SomeTemplate<void (Foo::*) (), Foo> t; // Compiles - '42'
t.PrintData(&Foo::printN);
SomeTemplate<void (Bar::*) (), Bar> t; // Compiles - '31'
t.PrintData(&Bar::printN);
SomeTemplate<void (Foo::*) (), Bar> t; // Won't compile, can't convert overloaded pointers
t.PrintData(&Foo::printN);
return 0;
}
In PrintData, an instance of the class is created and the member pointer passed is dereferenced on the instantiated version of the class, resulting in it's underlying function being called.
Templates make this approach somewhat more flexible, but I've yet to find a reason to use code such as this in a real situation however -- if anyone can find a one I'd love to be enlightened..

Related

How std::bind(&T::memberFunc, this) can always bind to std::function<void(void)> regardless of what T is?

As far as I know, the member function pointer only can be assigned to the pointer to member function type, and converted to any other except this will violate the standard, right?
And when calling std::bind(&T::memberFunc, this), it should return a dependent type which depend on T.(in std of VC++ version, it's a class template called _Binder).
So the question becomes to why one std::funcion can cover all _Binder(VC++ version) types.
class A
{
public:
void func(){}
};
class B
{
public:
void func(){}
};
std::function<void(void)> f[2];
A a;
B b;
f[0] = std::bind(&A::func, &a);
f[1] = std::bind(&B::func, &b);
And I can't picture what type of the member of std::funcion which stored the function would be like, unless I am wrong from the first beginning.
This question only covered the member function need to be called with it's instance.
But mine is about why one std::function type can hold all T types.
In short what is happening is that std::bind(&A::func, &a) returns an object of a class similar to
class InternalClass
{
A* a_; // Will be initialized to &a
public:
void operator()(void)
{
a_->func();
}
};
[Note that this is highly simplified]
The callable operator() function is what is matches the void(void) signature of the std::function<void(void)>.
I think the implementation would probably like this:
template</*...*/>
class std::bind</*...*/>
{
public:
std::bind(callable_t call, param_t p)
{
_func = [call, p]()/* using lambda to capture all data for future calling */
{
p->call();
};
}
operator std::function<void(void)>()
{
return _func;
}
private:
std::function<void(void)> _func;
};
And lambda is the key.

Overloading a C++ template class virtual function

Below is the code to recreate the problem I am having. Base class is a template class with the virtual function foo. foo has a default implementation that adds the passed in arguments.
SimpleDerived derives from Base, specializing it with std::string. SimpleDerived overloads the virtual Base<T>::foo() function. This class compiles fine and its foo outputs as expected when called in main.
#include <iostream>
template<class T>
struct Base
{
virtual void foo(T val)
{
T local = val + val; // THE OFFENDING LINE OF CODE
std::cout << "Base" << std::endl;
}
};
struct SimpleDerived : public Base<std::string>
{
virtual void foo(std::string val)
{
std::cout << "SimpleDerived" << std::endl;
}
};
struct SimpleObject
{
int value;
};
struct ComplexDerived : public Base<SimpleObject>
{
virtual void foo(SimpleObject val)
{
std::cout << "ComplexDerived" << std::endl;
}
};
int main(void)
{
Base<int> base;
base.foo(2);
SimpleDerived simpleDerived;
simpleDerived.foo("hello world");
SimpleObject object;
ComplexDerived complexDerived;
complexDerived.foo(object);
return 0;
}
ComplexDerived derives from Base, specializing it with a custom struct SimpleObject. ComplexDerived overloads foo as well. However, this is the root of the problem. If I try to compile this I get:
quicktest.cpp: In member function ‘void Base<T>::foo(T) [with T = SimpleObject]’:
quicktest.cpp:47:1: instantiated from here
quicktest.cpp:8:19: error: no match for ‘operator+’ in ‘val + val’
Obviously, there is no operator "+" for SimpleObject. But here is my confusion.. the compiler is being asked to implement Base<SimpleObject>::foo because this is what ComplexDerived inherits from. However, I never use or call Base<SimpleObject>::foo. So should the compiler be trying to generate this base class function?
Paragraph 14.7.1/10 of the C++11 Standard specifies:
An implementation shall not implicitly instantiate a function template, a member template, a non-virtual
member function, a member class, or a static data member of a class template that does not require instantiation. It is unspecified whether or not an implementation implicitly instantiates
a virtual member function of a class template if the virtual member function would not otherwise be instantiated. [...]
In other words, the behavior in this case is implementation-specific.
While in theory the compiler could figure out that the call to the base class's implementation of foo() won't ever be invoked (since the function call does not occur through a reference or pointer) and avoid instantiating it, this behavior is not mandated by the Standard.

What does this A<B>::c("d") construction mean? Name space with a template?

It looks like c is a function that takes "d" as argument. I know that :: is used to indicated name spaces and their sub-name spaces. But what A<B> mean? I know that B is class. I also know templates can be used for classes, functions and structures. But in this example it looks like we use a template for a name space.
It means you have a class template called A accepting a type parameter, and you instantiate that template with type B as its type argument.
That class template, in turn, defines either (1) a static member callable object c (could be a regular function) which accepts an object of a type to which a string literal is convertible, or (2) a type alias c for a type which is constructible from a string literal (and in that case you are constructing a temporary of that type).
In both cases, you access an entity defined inside class template A by using the same scope resolution operator (::) that you would use to access an entity defined inside a namespace (after all, both classes and namespaces define a scope).
As an example of (1) (live example):
#include <iostream>
struct B { };
template<typename T>
struct A
{
static void c(const char* s) { std::cout << s; }
};
int main()
{
A<B>::c("d");
}
As another example of (1) using a callable object rather than a function (live example):
#include <iostream>
struct B { void operator () (const char* c) { std::cout << c; } };
template<typename T>
struct A
{
static T c;
};
template<typename T>
T A<T>::c;
int main()
{
A<B>::c("d");
}
As an example of (2) (live example):
#include <iostream>
struct B { B(const char* s) { std::cout << s; } };
template<typename T>
struct A
{
typedef T c;
};
int main()
{
A<B>::c("d");
}
The scope resolution operator :: is used both with namespaces and fully qualified members.
In your example, c() looks like a static method exposed by the A<B> template class. Static members have to be fully qualified when accessed outside of their class.
As others rightfully point out, c can also be a callable static member (e.g. an instance of a type that overrides operator()(const char *)), or an alias to a type constructible from a const char *, or a public class or struct nested in A<B> that is constructible from a const char *.
(In the latter two cases, the constructor of that type is called only for its side-effects, since the created instance is not stored anywhere.)

function pointer from one class to member function of any class

I'm having difficulties defining a function pointer that can point to any member function (not just member functions for the specified class).
For instance, C++ forces me to specify the class that a function pointer to a member function would point to:
typedef void (Foo::*MyFunctionPointerTypeName)(int);
but what if the class member function that this function pointer is going to point to isn't in Foo? How then would I write this, or what alternative approach could I use?
Update: For anyone looking for a quick answer on how to accomplish this with a C++11 std::function (as tutorials on the subject seem to assume alot of the reader):
Definition (from within Foo):
std::function<void(int)> _fun;
Binding (from any class):
objFoo->_fun = std::bind(&SomeOtherClass::memberFunction,
this, std::placeholders::_1);
Calling it (from within Foo)
if(_fun != nullptr) _fun(42);
If your function has no parameters, you can remove std::placeholders::_1. And if your function has two parameters you'll need to also add std::placeholders::_2 as a parameter to std::bind. Similarly for three parameters, four parameters, etc.
You cannot write a member pointer that could point to a member of any class. Remember: one of the arguments of a member pointer is the class instance itself. And pointers are typed, so the type of its arguments is very much a part of the pointer's type.
You can use std::function however, which can store all sorts of callables. How you would actually call it (ie: what parameters you give it) depends on your needs, as you haven't explained what you're trying to do.
Use inheritance:
#include <iostream>
struct Foo {};
struct Bar : public Foo
{
int F0()
{
return 0;
}
};
struct Baz : public Foo
{
int F1()
{
return 1;
}
};
int main(int argc, char **argv)
{
int (Bar::*pF0)() = &Bar::F0;
int (Baz::*pF1)() = &Baz::F1;
int (Foo::*pointer1)() = static_cast<int (Foo::*)()>(pF0);
int (Foo::*pointer2)() = static_cast<int (Foo::*)()>(pF1);
Bar r;
Baz z;
// Pointer to Foo member function calling Bar member function
std::cout << (r.*pointer1)() << '\n';
// Pointer to Foo member function calling Baz member function
std::cout << (z.*pointer2)() << '\n';
return 0;
}
Output:
0
1
Hope it helps.

C++ SFINAE with CRTP, G++ compile error

I would like to know if the following code are valid.
The original intension is that, I like a base class that dispatch calls to a certain member to either derived class members if it is there or fall back to default behaviors if derived class does not have this member. Another use is that this base class can be used by itself and the Derived template parameter becomes a implementation policy. Anyway, the following MWE compiles and runs correctly with clang++, Intel, icpc and MSVS. However it fails with g++ (from 4.4 to 4.6, any version I had a hand on) with the error message at the end of the question.
If I change the call at point (1), (2), (3) to call_dispatch (which was the sort of thing I did originally), g++ does not complain anymore. I don't think it is a good practice to have the dispatch function and the caller having the same name. I was just curious if it will work, and curiously enough to try it out (I have no idea how does this idea come to me). My rationale behind this is that, at pint (1), call is invoked with one parameter, so the overload resolution will not match its caller, the zero parameter one. It will not match the SFINAE one at point (2) either, since D2 does not have the member, and then it shall match the one at point (3). Just as in the situation when (1)-(3) are named call_dispatch.
But g++ does not agree with me and other compilers. So, is it an incorrect implementation of g++ or the code itself is invalid? Besides the error message is really confusing. Where does the void (B<D2>::*)() and &B<D2>::call come from? Int he called the member pointer was defined as D2's member.
#include <iostream>
#include <functional>
template <typename Derived>
class B
{
public :
void call ()
{
call<Derived>(0); //----------------------------------------- (1)
}
private :
template <typename D, void (D::*)()> class SFINAE {};
template <typename D>
void call (SFINAE<D, &D::call> *) //---------------------------- (2)
{
static_cast<Derived *>(this)->call();
}
template <typename D>
void call (...) //--------------------------------------------- (3)
{
std::cout << "Call B" << std::endl;
}
};
class D1 : public B<D1>
{
public :
void call ()
{
std::cout << "Call D1" << std::endl;
}
};
class D2 : public B<D2> {};
int main ()
{
D1 d1;
D2 d2;
d1.call();
d2.call();
return 0;
}
Error:
foo.cpp: In member function ‘void B<Derived>::call() [with Derived = D2]’:
foo.cpp:48:13: instantiated from here
foo.cpp:11:9: error: ‘&B<D2>::call’ is not a valid template argument for type ‘void (D2::*)()’ because it is of type ‘void (B<D2>::*)()’
foo.cpp:11:9: note: standard conversions are not allowed in this context
Edit
Though I have not fully understand what goes wrong in the above code yet. But I think there is a another way without specifically construct a SFINAE class but archive the same effect.
#include <iostream>
template <typename Derived>
class B
{
public :
void call ()
{
call_dispatch(&Derived::call);
}
template <typename C>
void call_dispatch (void (C::*) ())
{
static_cast<Derived *>(this)->call();
}
void call_dispatch (void (B<Derived>::*) ())
{
std::cout << "Call B" << std::endl;
}
private :
};
class D1 : public B<D1>
{
public :
void call ()
{
std::cout << "Call D1" << std::endl;
}
};
class D2 : public B<D2> {};
int main ()
{
D1 d1;
D2 d2;
d1.call();
d2.call();
return 0;
}
Basically, because D1 and D2 both are derived from B, so the expression &Derived::call will always be resolved. In D1 it resolved to &D1::call, then the template version member is used. In D2, it does not have its own call, so &D2::call is resolved to &B::call, and thanks to
#DavidRodríguez-dribeas, who points out that now &D2::call has the type B::call, therefore the template and the non-template members equally match, but non-template is preferred. So the default call is used.
Can help me see if there is any defect in this new code?
Where does the void (B::*)() and &B::call come from?
The type of a pointer to member is not the type on which you obtained such pointer, but the type on which the member is defined.
struct base { int x; };
struct derived : base {};
int main() {
std::cout << std::is_same< decltype(&derived::x), int (base::*) >::value << std::endl;
}
The above program prints 1. In your case, when you use &D::base, the compiler finds B<D2>::call as a member of the base template, and that is the result of the expression: void (B<D2>::*)().
Your instantiation of SFINAE is expecting the function pointer template argument to be of type void (D2::*)(), but instead is of type void (B<D2>::*)() (because call is not overidden in D2, it uses the one defined in B<D2>).
Edit
It is not the instantiation of template <typename D>
void call (SFINAE<D, &D::call> *) that is failing here. There is no substitution error there. The substitution error occurs with the instantiation of SFINAE<B<D2>, &B<D2>::call>, of which there is no fallback instantiation, hence the error.