Unable to Run Program Using a Pointer to a Template Method Inside a Template Class

Ref: https://goodliffe.blogspot.com/2011/07/c-declaring-pointer-to-template-method.html
Seems like others don't have the issues I am encoutering with this blog, but I have been unable to build/run case 5. I added this simple main() function:
int main()
{
	PointerToNormalMemberFunction(); // target 1
	PointerToTemplateMemberFunction(); // target 2
	PointerToTemplateMemberFunctionWithTwoParameters(); // terget 3
	PointerToTemplateMemberInTemplateClass(); // target 4
//	HoldingAPointerToTemplateMemberInTemplateClass(); // target 5 ---> Had to comment this out
}

Open in new window

In the referenced link are five cases. I am having trouble with case 5. Here is the code for this last case. Can you get a simple test program to work with this case 5? Thanks!
#pragma once

#include <iostream>

template<typename TYPE>
class Target5
{
public:
	Target5(const TYPE &value) : value(value) {}
	TYPE value;

	template <typename T>
	void OneParam(T a)
	{
		std::cout << "Target5::OneParam(" << value << "," << a << ")\n";

		typedef void (Target5<E>::*MethodTypeToCall)(T);
		// Here, the compiler picks the right overload
		MethodTypeToCall toCall = &Target5<E>::Private;
		// In this case, the compiler does not let us write the following line (parse error):
		//MethodTypeToCall toCall = &Target5<E>::Private<t;;
		(this->*toCall)(a);
	}

	template <typename T1, typename T2>
	void TwoParam(T1 a, T2 b)
	{
		std::cout << "Target5::TwoParam(" << value << "," << a << "," << b << ")\n";

		typedef void (Target5<E>::*MethodTypeToCall)(T1, T2);
		MethodTypeToCall toCall = &Target5<E>::Private; // compiler picks the right overload
		// you can't add the method's template parameters to the end of that line
		(this->*toCall)(a, b);
	}

private:

	template <typename T>
	void Private(T a)
	{
		std::cout << "Target5::Private(" << value << "," << a << ")\n";
	}
	template <typename T1, typename T2>
	void Private(T1 a, T2 b)
	{
		std::cout << "Target5::Private(" << value << "," << a << "," << b << ")\n";
	}
};

inline
void HoldingAPointerToTemplateMemberInTemplateClass()
{
	Target5<r> target('c');

	void (Target5<r>::*oneParam)(int) = &Target5<r>::OneParam;
	(target.*oneParam)(7);
	void (Target5<r>::*twoParam)(float, int) = &Target5<r>::TwoParam;
	(target.*twoParam)(7.5, 7);
}

Open in new window

Errors when building. How should I define 'E' and 'r' and get a simple test program to run?
1>Main_Targets.cpp
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(17): error C3861: 'E': identifier not found
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(17): note: This diagnostic occurred in the compiler generated function 'void Target5<TYPE>::OneParam(T)'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(48): note: see reference to class template instantiation 'Target5<TYPE>' being compiled
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(19): error C3861: 'E': identifier not found
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(19): note: This diagnostic occurred in the compiler generated function 'void Target5<TYPE>::OneParam(T)'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(30): error C3861: 'E': identifier not found
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(30): note: This diagnostic occurred in the compiler generated function 'void Target5<TYPE>::TwoParam(T1,T2)'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(31): error C3861: 'E': identifier not found
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(31): note: This diagnostic occurred in the compiler generated function 'void Target5<TYPE>::TwoParam(T1,T2)'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(53): error C2065: 'r': undeclared identifier
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(53): error C2923: 'Target5': 'r' is not a valid template type argument for parameter 'TYPE'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(53): error C2514: 'Target5': class has no constructors
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(7): note: see declaration of 'Target5'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(55): error C2065: 'r': undeclared identifier
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(55): error C2923: 'Target5': 'r' is not a valid template type argument for parameter 'TYPE'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(55): error C2955: 'Target5': use of class template requires template argument list
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(7): note: see declaration of 'Target5'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(55): error C2440: 'initializing': cannot convert from 'overloaded-function' to 'void (__thiscall Target5::* )(int)'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(55): note: None of the functions with this name in scope match the target type
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(57): error C2065: 'r': undeclared identifier
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(57): error C2923: 'Target5': 'r' is not a valid template type argument for parameter 'TYPE'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(57): error C2955: 'Target5': use of class template requires template argument list
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(7): note: see declaration of 'Target5'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(57): error C2440: 'initializing': cannot convert from 'overloaded-function' to 'void (__thiscall Target5::* )(float,int)'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(57): note: None of the functions with this name in scope match the target type

Open in new window

LVL 33
phoffric\Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

phoffric\Author Commented:
BTW, just to demo an alternative short definition approach, I added to case 4 the following:
void PointerToTemplateMemberInTemplateClass()
{  ...
	auto oneParam2 = &Target4<char>::OneParam<float>;
	(target.*oneParam2)(6.25);

	auto twoParam2 = &Target4<char>::TwoParam<float, int>;
	(target.TwoParam)(6.825F, 7);
}

Open in new window

ZoppoCommented:
Well, you first should fix the obvious errors, i.e.:

- target5.h(17): error C3861: 'E': identifier not found
      typedef void (Target5<E>::*MethodTypeToCall)(T); // what's that 'E'? I guess 'T' is intended

- target5.h(53): error C2065: 'r': undeclared identifier
      Target5<r> target('c'); // what is 'r'?

ZOPPO
phoffric\Author Commented:
Hi Zoppo, Looks like you posted 2 minutes before my last edit. Here is what I added in the OP:
Errors when building. How should I define 'E' and 'r' and get a simple test program to run?
They are the obvious errors. I tried a few WAGs at defining them, but no luck.
Become a Microsoft Certified Solutions Expert

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

phoffric\Author Commented:
OP Line 17:
typedef void (Target5<E>::*MethodTypeToCall)(T);

Open in new window

I believe the intention is that MethodTypeToCall is a pointer to class Target5<E> member function, and it takes a parameter of type T.
phoffric\Author Commented:
I tried adding E as an additional template typename to Target5, and dropped into a rabbit hole inside a rabbit hole.
evilrixSenior Software Engineer (Avast)Commented:
I'm looking at this on a mobile, so my assessment is a little hampered  but it looks like E can be any type you like as long as it can be streamed to an ostream and r looks like it should be a char. E is unrelated to T, T1 and T2. E is the class template type and Tn is the function template type.
phoffric\Author Commented:
@ricky,
No rush.
		// In this case, the compiler does not let us write the following line (parse error):
		//MethodTypeToCall toCall = &Target5<E>::Private<t;;

Open in new window

Heh, clearly that line gives a parse error. I wonder what he had originally.

For the 'r' issue, I did substitute r with char , but got different errors.

For the 'E' issue, I tried adding E as another typename to Target5 template, but got errors.
evilrixSenior Software Engineer (Avast)Commented:
There you go... tinker as you wish :)

#include <iostream>

using E = int;
using r = int;

template<typename TYPE>
class Target5
{
public:
	Target5(const TYPE &value) : value(value) {}
	TYPE value;

	template <typename T>
	void OneParam(T a)
	{
		std::cout << "Target5::OneParam(" << value << "," << a << ")\n";

		typedef void (Target5<E>::*MethodTypeToCall)(T);
		// Here, the compiler picks the right overload
		MethodTypeToCall toCall = &Target5<E>::Private;
		// In this case, the compiler does not let us write the following line (parse error):
		//MethodTypeToCall toCall = &Target5<E>::Private<t;;
		(this->*toCall)(a);
	}

	template <typename T1, typename T2>
	void TwoParam(T1 a, T2 b)
	{
		std::cout << "Target5::TwoParam(" << value << "," << a << "," << b << ")\n";

		typedef void (Target5<E>::*MethodTypeToCall)(T1, T2);
		MethodTypeToCall toCall = &Target5<E>::Private; // compiler picks the right overload
		// you can't add the method's template parameters to the end of that line
		(this->*toCall)(a, b);
	}

private:

	template <typename T>
	void Private(T a)
	{
		std::cout << "Target5::Private(" << value << "," << a << ")\n";
	}
	template <typename T1, typename T2>
	void Private(T1 a, T2 b)
	{
		std::cout << "Target5::Private(" << value << "," << a << "," << b << ")\n";
	}
};

inline
void HoldingAPointerToTemplateMemberInTemplateClass()
{
	Target5<r> target('c');

	void (Target5<r>::*oneParam)(int) = &Target5<r>::OneParam;
	(target.*oneParam)(7);
	void (Target5<r>::*twoParam)(float, int) = &Target5<r>::TwoParam;
	(target.*twoParam)(7.5, 7);
}

int main()
{
	HoldingAPointerToTemplateMemberInTemplateClass();
}

Open in new window

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
evilrixSenior Software Engineer (Avast)Commented:
FWIW, creating pointers to template member functions is no different from creating pointers to non-template member functions. You just have to make sure you specify the full specialisation. In other words you can do this...

class myclass { template <typename T> void foo(){} };

&myclass::foo<int>;

but not this...

&myclass::foo;

That's because a template is literally just a design pattern, it doesn't exist as a concrete object and so has no address to take. In the blog example, the full template specification is being provided by the typedef and so the compiler is able to figure out what the full template specification is when you perform the assignment, but that's just syntactic sugar. The point is, you can't take an address of a template unless it's been fully specialised because there is nothing to take the address of until that point.

The syntax is pretty nasty, but that's just a matter of getting used to it and isn't really any worse than the non-template syntax (also nasty). One way to avoid that is to use std::bind and auto. Using raw pointers is something best avoided unless you're a masochist. Whilst I fully understand and know how to use all this syntax, it's not something I would do out of choice when C++ provides you tools to avoid all this nasty messy around. Look at how much cleaner the following code is.

#include <iostream>
#include <functional>

using namespace std::placeholders;  // for _1, _2, _3...

using E = int;
using r = int;

template<typename TYPE>
class Target5
{
public:
	Target5(const TYPE &value) : value(value) {}
	TYPE value;

	template <typename T>
	void OneParam(T a)
	{
		std::cout << "Target5::OneParam(" << value << "," << a << ")\n";
		auto const & toCall = std::bind(&Target5<E>::Private<T>, this, _1);
		toCall(a);
	}

	template <typename T1, typename T2>
	void TwoParam(T1 a, T2 b)
	{
		std::cout << "Target5::TwoParam(" << value << "," << a << "," << b << ")\n";
		auto const & toCall = std::bind(&Target5<E>::Private<T1, T2>, this, _1, _2);
		toCall(a, b);
	}

private:

	template <typename T>
	void Private(T a)
	{
		std::cout << "Target5::Private(" << value << "," << a << ")\n";
	}
	template <typename T1, typename T2>
	void Private(T1 a, T2 b)
	{
		std::cout << "Target5::Private(" << value << "," << a << "," << b << ")\n";
	}
};

inline
void HoldingAPointerToTemplateMemberInTemplateClass()
{
	Target5<r> target('c');

	auto const & oneParam = std::bind(&Target5<r>::OneParam<int>, std::ref(target), _1);
	oneParam(7);

	auto const & twoParam = std::bind(&Target5<r>::TwoParam<float, int>, std::ref(target), _1, _2);
	twoParam(7.5, 7);
}

int main()
{
	HoldingAPointerToTemplateMemberInTemplateClass();
}

Open in new window


The only thing I would say is that std::bind can be a little tricky to get your head around at first, but once the penny drops as to how it works, you'll soon realise it's actually quite easy to use and is a very powerful tool - although somewhat superseded by lambdas (that said, it's useful for this kind of thing).
phoffric\Author Commented:
Thanks for the two using lines! :) Will start to digest your 2nd post.

 I mentioned that I had replaced the r with char and had errors, so I thought I would try that here as well.
using E = int;
using r = char;

Open in new window

Now I get those compiler errors again. Was surprised to see "error C2248: 'Target5<int>::Private': cannot access private member declared in class 'Target5<int>'
1>Main_Targets.cpp
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(28): error C2248: 'Target5<int>::Private': cannot access private member declared in class 'Target5<int>'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(48): note: see declaration of 'Target5<int>::Private'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(26): note: see declaration of 'Target5<int>'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(64): note: see reference to function template instantiation 'void Target5<r>::OneParam<int>(T)' being compiled
1>        with
1>        [
1>            T=int
1>        ]
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(64): note: see reference to function template instantiation 'void Target5<r>::OneParam<int>(T)' being compiled
1>        with
1>        [
1>            T=int
1>        ]
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(31): error C2440: '->*': cannot convert from 'Target5<r> *' to 'Target5<int> *'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(31): note: Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(31): error C2647: '->*': cannot dereference a 'MethodTypeToCall' on a 'Target5<r> *'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(40): error C2248: 'Target5<int>::Private': cannot access private member declared in class 'Target5<int>'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(53): note: see declaration of 'Target5<int>::Private'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(26): note: see declaration of 'Target5<int>'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(66): note: see reference to function template instantiation 'void Target5<r>::TwoParam<float,int>(T1,T2)' being compiled
1>        with
1>        [
1>            T1=float,
1>            T2=int
1>        ]
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(66): note: see reference to function template instantiation 'void Target5<r>::TwoParam<float,int>(T1,T2)' being compiled
1>        with
1>        [
1>            T1=float,
1>            T2=int
1>        ]
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(42): error C2440: '->*': cannot convert from 'Target5<r> *' to 'Target5<int> *'
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(42): note: Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>c:\users\ - limited\source\repos\c++template\ptrdatamembers\target5.h(42): error C2647: '->*': cannot dereference a 'MethodTypeToCall' on a 'Target5<r> *'

Open in new window

evilrixSenior Software Engineer (Avast)Commented:
Target<into> and Target<char> are different classes. Remember, a template is just a pattern, concrete instances of different types are exactly that, different types so one cannot access the others private member's.
phoffric\Author Commented:
>> Target<int> and Target<char> are different classes.
Thanks. When you say it, it makes sense. :)
When error is: error C2248:
'Target5<int>::Private': cannot access private member declared in class 'Target5<int>', I don't even see  Target<char> , so I had trouble deciphering this error message.

When I made both using statements char, no errors and run was correct.

Given your explanation, my belief is that the OP link should not have ever introduced the E type, since it must access Target5<TYPE>. Do you agree in this generalization. I did confirm that by removing E, and replacing it with TYPE, then the program builds/runs OK.
evilrixSenior Software Engineer (Avast)Commented:
Yes, I agree. Without wanting to be critical, I don't think the blog post is a particularly good example of what is actually quite a simple concept. I think it over complicated things and the example class is confusing for the reasons you've established.

Generally, the boilerplate of an example should be kept as trivial as possible to allow focus on the actual issue being discussed. That all said, I think you've now got your head around this. All I'd say is take time to understand this concept then use std::bind, in much the same was as you'd take time to understand C arrays then always use vector  :)
phoffric\Author Commented:
Thanks for helping me with Templated Pointers to Class Members. I still have to review the another post about bind and masochism. Whilst I have heard that binding and masochism goes hand in hand, I'm not sure that is where I want this thread to go. However, I would like to see what you mean if you are talking about std::bind. I'll look at this other post on Tuesday. :)
evilrixSenior Software Engineer (Avast)Commented:
No worries, Paul. No rush  take time to digest. Yes, bind can be tricky at first, but it's one of those tools that so incredibly useful that the pain in learning to use it is worth it.

It's based on Boost's bind and so reading Boost's documentation for it (which is really thorough and gives loads of examples) is worth while.

The introduction of lambdas in C++ has mostly replaced the need for bind, but in cases like this I still prefer using bind as it's perfect for this.

Of course, it's still important to understand what's going on behind the scenes inside bind, so a good grounding in the original material of the OP is still a must.
phoffric\Author Commented:
Still trying to understand the OP link a little more where two of the author's comments (lines 16 and 32 below) are:
// In this case, the compiler does not let us write the following line (parse error):
// you can't add the method's template parameters to the end of that line
So, naturally, I tried to figure out what I cannot do and then try to track it down in the C++ spec. But I had no luck. The below program produces the expected output (although I know that doesn't mean that it is correct code). Since my changes (noted by "//@@") compiles/builds/runs seemingly OK, I am not sure what kind of change the author is referring to. Any ideas? (In my experience, learning to read compiler/liner error messages is very important; so I was hoping to generate a new kind of error for me to see.)
template<typename TYPE>
class Target5
{
public:
	Target5(const TYPE &value) : value(value) {}
	TYPE value;

	template <typename T>
	void OneParam(T a)
	{
		std::cout << "Target5::OneParam(" << value << "," << a << ")\n";

		typedef void (Target5<TYPE>::*MethodTypeToCall)(T);
		// Here, the compiler picks the right overload
		MethodTypeToCall toCall = &Target5<TYPE>::Private;
		// In this case, the compiler does not let us write the following line (parse error):
		//@@ here is my guess as to what the author in the link was talking about.
		//@@ I am trying to get a compiler error but failed
//		MethodTypeToCall toCall2 = &Target5<TYPE>::Private<T>; //@@ works OK
		auto toCall2 = &Target5<TYPE>::Private<T>; //@@ Still works OK
		(this->*toCall)(a);
		(this->*toCall2)(a);
	}

	template <typename T1, typename T2>
	void TwoParam(T1 a, T2 b)
	{
		std::cout << "Target5::TwoParam(" << value << "," << a << "," << b << ")\n";

		//typedef void (Target5<TYPE>::*MethodTypeToCall)(T1, T2); //@@ eliminate this and next line
		//MethodTypeToCall toCall = &Target5<TYPE>::Private; // compiler picks the right overload
		// you can't add the method's template parameters to the end of that line //@@ What exactly can't I do?
//		MethodTypeToCall toCall2 = &Target5<TYPE>::Private<T1, T2>;  //@@ works OK
		auto toCall2 = &Target5<TYPE>::Private<T1, T2>; //@@ Still work OK; can eliminate above 2 LOCS
		(this->*toCall2)(a, b);
//		(this->*toCall)(a, b);
	}

private:

	template <typename T>
	void Private(T a)
	{
		std::cout << "Target5::Private(" << value << "," << a << ")\n";
	}
	template <typename T1, typename T2>
	void Private(T1 a, T2 b)
	{
		std::cout << "Target5::Private(" << value << "," << a << "," << b << ")\n";
	}
};

template <typename r, r val>		//@@ made this a tmplate function
void HoldingAPointerToTemplateMemberInTemplateClass()
{
	Target5<r> target(val);

	void (Target5<r>::*oneParam)(int) = &Target5<r>::OneParam;
	(target.*oneParam)(7);
	void (Target5<r>::*twoParam)(float, int) = &Target5<r>::TwoParam;
	(target.*twoParam)(7.5, 7);

	std::cout << std::endl;
}

Open in new window

evilrixSenior Software Engineer (Avast)Commented:
Hey, Paul. I'm not in a position to look at this now, but I'll take a look tomorrow. I know we're in different timezones so I hope that's okay.
phoffric\Author Commented:
Of course that is ok. No rush. I an just exploring new areas because it is challenging. Thank you for the update. :)

And thank you for your explanations. You should consider giving a 1 hour presentation at a C++ convention like cppcon but maybe somewhere closer to you.
evilrixSenior Software Engineer (Avast)Commented:
>> typedef void (Target5<TYPE>::*MethodTypeToCall)(T);
>> // Here, the compiler picks the right overload
>> MethodTypeToCall toCall = &Target5<TYPE>::Private;

So, basically, because the compiler knows the static type of the function to expect (via the typedef), it is able to resolve the type of the function without you needing to explicitly instantiate it. As in, you don't need to do this...
MethodTypeToCall toCall = &Target5<TYPE>::Private<T>;

If you think about it, it's no different from the following. The compiler doesn't need you to specifically case to the correct overload as it can figure it out based upon the static type of the pointer.

// Use free standing functions just to keep the example simple
void foo(int) { }
void foo(int, int) { }

// yucky, yucky syntax that I always forget and have to look up :(
typedef void (*foo_int)(int);
typedef void (*foo_int_int)(int, int);

int main()
{
   // Compiler is able to resolve these overloads based upon pointer's static type
   foo_int pFooInt = foo;
   foo_int_int pFooIntInt = foo;
}

Open in new window


>> MethodTypeToCall toCall2 = &Target5<TYPE>::Private<T>; //@@ works OK

To the best of my knowledge, this is perfectly valid. You're just explicitly instantiating the function and that's exactly what you'd have to do when (for example) using std::bind (because the compiler wouldn't be able to inferr the type).

That is a pretty old post (2011) and he was using a pretty old version of gcc (4.2.1) and so this could of been a case of the compiler not fully supporting the standard.

I tested this using gcc 4.3.1 (the oldest I could find) and, sure enough, it works just fine.

https://ideone.com/Gx9cCP

I honestly have no idea why he things that would not be valid.

I hope this helps and sorry I can't really answer your 2nd question. Either we're being dumb (probably), he's wrong or he's just done a bad job of explaining a real problem and so we're not getting it. Unfortunately, without more information I can't really say.
phoffric\Author Commented:
Thanks for your confirmations!

>> That is a pretty old post (2011) and he was using a pretty old version of gcc (4.2.1)
I better start checking the post dates and compiler versions, as well as the author's reputation (if I can find it).
I doubt you (and me) are being dumb in trying to reproduce his compiler error scenarios. I think either we are misinterpreting his remarks about something he tried (and not shown), or the compiler is buggy (and I also have struggled with older, error prone, g++ compilers - 4.6, I think it was), or maybe he is new to this subject matter, and just writing up what he discovered.

Well, I think we covered a lot of ground in this thread. I hope to look at your std::bind in the next few days after reading up on it. I am struggling at the moment with a derivative problem in this thread - getting nasty compiler errors. If I don't figure it out, I'll show some problem areas in another question. The topic will be passing arguments. I see examples online, but I am still either making some mistakes in argument passing with template parameters, or maybe what I am trying to do can't be done. I'll start taking some online examples and see whether I can morph it into the above working program. If I do figure it out, I'll post it here.

Thanks again for your help.
phoffric\Author Commented:
Well, Pete's reputation in book writing is above average.
https://www.amazon.com/Pete-Goodliffe/e/B00M0WHEAA?ref=sr_ntt_srch_lnk_2&qid=1552589662&sr=8-2
Now, you have a lot of blogs. Maybe you can consolidate them into a book and sell it on Amazon. I'll buy the first copy. :)
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.