c++ member functions with unresolved overload calling member functions - c++

I'm trying to make an object with a member function that calls another member function like so
foo foo1 = new foo(1, 2);
foo1.print(printj);
I have class:
class foo
{
public:
foo(int x, int y) {i = x; j = y;};
void const print(void const f());
void const printi();
void const printj();
private:
int i;
int j;
}
and my implementation is something like:
void const foo::printi(){
std::cout << i;
}
void const foo::printj(){
std::cout << j;
}
void const foo::print(void const f()){
f();
}
I'm getting an error of
[Error] no matching function for call to 'foo::print()'
Why is that, and how can i fix it?

You need to:
Declare the pointer-to-member function parameter as such:
void const print(void const (foo::*f)());
Pass the member function pointer correctly:
foo1.print(&foo::printj);
Call it with an actual instance (member function call requires an instance):
void const foo::print(void const (foo::*f)()){
(this->*f)();
}
Alternatively you can make the instance an additional parameter or use std::bind or boost::bind to bind them together.

that is not the way how to declare a pointer to a member function you have to declare it this way:
const void (Foo::*ptrFUnc)(void) // or any number of parameters and type
this example shows how:
#include <iostream>
using namespace std;
class Foo
{
public:
void print(const void(Foo::*Bar)()const)const;
const void FooBar()const;
const void Baz ()const;
};
void Foo::print(const void(Foo::*Bar)()const)const
{
(this->*Bar)();
}
const void Foo::FooBar()const
{
cout << "FooBar()" << endl;
}
const void Foo::Baz()const
{
cout << "Baz()" << endl;
}
int main()
{
Foo theFoo;
theFoo.print(theFoo.Baz);
theFoo.print(theFoo.FooBar);
return 0;
}

Note: This answer is aimed at general-case scenarios and future-proofing, and thus examines the possibility of accepting member functions with different numbers of arguments, and of modifying the function in the future. If this isn't an issue, the easiest solution is to manually specify the pointer-to-member-function, as described in the other answers.
A short summary is at the bottom.
There are also two alternatives to declaring the function's type manually, as shown in the other answers, both involving templates:
Declare it manually.
First alternative: Use templates to specialise the pointer-to-member-function, while explicitly specifying the class.
Second alternative: Use templates to deduce the pointer-to-member-function, with no explicit specifications.
In all three cases (manual declaration, and the two alternatives listed here), the usage syntax is identical:
foo1.print(&foo::printj);
As the other answers show, the syntax for declaring it manually is as follows:
// #1: Explicit declaration.
void const foo::print(void const (foo::* f)()) {
(this->*f)();
}
I won't go into much detail on this, as they already cover it. However, this option does have the issue that if you want to accept pointers to member functions which take one or more parameters, you need to manually overload it to accomodate this.
void const foo::print(void const (foo::* f)());
void const foo::print(void const (foo::* f)(int), int);
// And so on...
The first alternative looks a bit complex if you're not used to templates, but is relatively simple to implement.
// 2a: Simplest implementation.
template<typename Return, typename... ArgTypes>
void const foo::print(Return (foo::* f)(ArgTypes...), ArgTypes... args) {
(this->*f)(args...);
}
Or...
// 2b: Works roughly the same way, but gives cleaner, more readable error messages.
template<typename Return, typename... ArgTypes, typename... Args>
void const foo::print(Return (foo::* f)(ArgTypes...), Args... args) {
(this->*f)(args...);
}
This accepts any pointer-to-member-function which points to a member of foo, regardless of return and parameter types. If the function takes parameters, it also accepts a number of parameters equal to that function's.
Note that the primary difference between the two is that if not passed the correct number of parameters for the function, the first will give an error about not being able to deduce ArgTypes... due to mismatched template parameter packs, while the second will give an error about not having the correct number of parameters to call f().
[Mechanically, the difference is that the first uses the same template parameter pack in both the pointer and the parameter list, which requires that it be identical in both places (and thus detects the error as a deduction failure when print() is called), while the second uses a separate template parameter pack for each (and thus detects the error as a parameter count mismatch when the pointed-to function, f, is called).]
The second alternative looks cleaner still, and provides cleaner error messages.
template<typename MemberFunction>
void const foo::print(MemberFunction f){
(this->*f)();
}
This can be easily modified to accept member functions which take parameters, similarly to the first alternative.
// 3: Take pointer-to-member-function and any function parameters as template parameters.
template<typename MemberFunction, typename... Args>
void const foo::print(MemberFunction f, Args... args){
(this->*f)(args...);
}
It will also give the cleanest error message if passed the wrong number of parameters for the function, because the error occurs when calling f instead of at overload resolution or template deduction. This makes it the easiest to troubleshoot, if necessary.
So, this leaves us with three options, one of which can be done either of two ways:
class foo
{
public:
foo(int x, int y) {i = x; j = y; test = 42;};
// -----
// #1.
void const print1(void const (foo::* f)());
// -----
// #2.
template<typename Return, typename... ArgTypes>
void const print2a(Return (foo::* f)(ArgTypes...), ArgTypes... args);
template<typename Return, typename... ArgTypes, typename... Args>
void const print2b(Return (foo::* f)(ArgTypes...), Args... args);
// -----
// #3.
template<typename MemberFunction, typename... Args>
void const print3(MemberFunction f, Args... args);
// -----
void const printi();
void const printj();
// For testing.
void const printParams(int i, bool b, char c, double d);
private:
int i;
int j;
public:
int test;
};
void const foo::print1(void const (foo::* f)()) {
(this->*f)();
}
template<typename Return, typename... ArgTypes>
void const foo::print2a(Return (foo::* f)(ArgTypes...), ArgTypes... args) {
(this->*f)(args...);
}
template<typename Return, typename... ArgTypes, typename... Args>
void const foo::print2b(Return (foo::* f)(ArgTypes...), Args... args) {
(this->*f)(args...);
}
template<typename MemberFunction, typename... Args>
void const foo::print3(MemberFunction f, Args... args) {
(this->*f)(args...);
}
// -----
void const foo::printi(){
std::cout << i;
}
void const foo::printj(){
std::cout << j;
}
void const foo::printParams(int i, bool b, char c, double d) {
std::cout << std::boolalpha;
std::cout << i << ' ' << b << ' ' << c << ' ' << d << '\n';
std::cout << std::noboolalpha;
}
// -----
foo foo1(1, 2);
Now, mechanically, all three options will accept a pointer-to-member-function, and work as intended. There are a few key differences, however:
The first requires the most work to update and maintain (you have to explicitly overload it), but guarantees that print1() will only take pointers-to-member-functions that you specifically allow; if you want it to only take a void const (foo::*)(), it won't take a void const (foo::*)(int) instead. If passed incorrect arguments, its error messages will be the least useful.
The second only takes a pointer-to-member-function for the specified class, but accepts any pointer-to-member-function for that class; this makes it easier to update and maintain. If passed incorrect arguments, its error messages will be somewhat useful, but will usually be about template deduction. Of the two versions, print2b() will give cleaner error messages when passed the wrong number of parameters.
The third takes anything, but gives the cleanest, most useful error messages if used incorrectly. This is because the error is generated when you call f, instead of when you call print3(). This is as easy to update and maintain as the second option, and opens the possibility to perform dispatching based on the type of pointer it's passed.
So, to demonstrate the difference in error messages, let's see what happens if...
[Error messages paraphrased from Clang, GCC, and MSVC.]
[Note that MSVC template parameter lists have trouble with variadic templates, and can't properly output parameter packs. However, the function's name still contains the full template parameter list.]
If passed a pointer-to-member-function with no parameters: All four work properly.
foo1.print1(&foo::printj); // Output: 2
foo1.print2a(&foo::printj); // Output: 2
foo1.print2b(&foo::printj); // Output: 2
foo1.print3(&foo::printj); // Output: 2
If passed a pointer-to-member-function that takes parameters, and its parameters: print1() fails.
foo1.print1(&foo::printParams, 3, true, '&', 8.8); // Error: Too many arguments.
foo1.print2a(&foo::printParams, 3, true, '&', 8.8); // Output: 3 true & 8.8
foo1.print2b(&foo::printParams, 3, true, '&', 8.8); // Output: 3 true & 8.8
foo1.print3(&foo::printParams, 3, true, '&', 8.8); // Output: 3 true & 8.8
If passed a pointer-to-member-function that takes parameters, and the wrong number of parameters: All four fail.
foo1.print1(&foo::printParams, 42); // Error: Too many arguments.
foo1.print2a(&foo::printParams, 42); // Error: Can't deduce template parameters,
// ArgTypes... could be <int, bool, char, double> or <int>.
foo1.print2b(&foo::printParams, 42); // Error: Not enough arguments to call f().
// Note: Clang deduces template parameters as:
// <const void, int, bool, char, double, int>
// Note: GCC deduces template parameters as:
// [with Return = const void; ArgTypes = {int, bool, char, double}; Args = {int}]
// Note: MSVC deduces template parameters as:
// <const void,int,bool,char,double,int>
foo1.print3(&foo::printParams, 42); // Error: Not enough arguments to call f().
// Note: Clang deduces template parameters as:
// <const void (foo::*)(int, bool, char, double), int>
// Note: GCC deduces template parameters as:
// [with MemberFunction = const void (foo::*)(int, bool, char, double); Args = {int}]
// Note: MSVC deduces template parameters as:
// <const void(__thiscall foo::* )(int,bool,char,double),int>
If passed a regular function pointer: All four fail.
void const bar() {}
foo1.print1(&bar); // Error: Can't convert void const (*)() to void const (foo::*)().
foo1.print2a(&bar); // Error: Can't deduce template parameters, mismatched function pointers.
foo1.print2b(&bar); // Error: Can't deduce template parameters, mismatched function pointers.
foo1.print3(&bar); // Error: void const (*)() isn't a pointer-to-member, can't be used with "->*".
If passed a pointer-to-member-function for the wrong class: All four fail.
class oof {
public:
void const printj() {}
};
foo1.print1(&oof::printj); // Error: Can't convert void const (oof::*)() to void const (foo::*)().
foo1.print2a(&oof::printj); // Error: Can't deduce template parameters, mismatched foo* and oof*.
foo1.print2b(&oof::printj); // Error: Can't deduce template parameters, mismatched foo* and oof*.
foo1.print3(&oof::printj); // Error: Can't use a void const (oof::*)() with a foo*.
If passed a pointer-to-member-data: All four fail.
foo1.print1(&foo::test); // Error: Can't convert int foo::* to void const (foo::*)().
foo1.print2a(&foo::test); // Error: Can't deduce template parameters, mismatched
// int foo::* and Return (foo::*)(ArgTypes...).
foo1.print2b(&foo::test); // Error: Can't deduce template parameters, mismatched
// int foo::* and Return (foo::*)(ArgTypes...).
foo1.print3(&foo::test); // Error: int foo::* can't be used as a function.
If passed a regular pointer: All four fail.
foo1.print1(&foo); // Error: Can't convert foo* to void const (foo::*)().
foo1.print2a(&foo); // Error: Can't deduce template parameters, mismatched
// foo* and Return (foo::*)(ArgTypes...).
foo1.print2b(&foo); // Error: Can't deduce template parameters, mismatched
// int foo::* and Return (foo::*)(ArgTypes...).
foo1.print3(&foo); // Error: foo* isn't a pointer-to-member, can't be used with "->*".
If passed an integral value: All four fail.
foo1.print1(3); // Error: Can't convert int to void const (foo::*)().
foo1.print2a(3); // Error: Can't deduce template parameters, mismatched
// int and Return (foo::*)(ArgTypes...).
foo1.print2b(3); // Error: Can't deduce template parameters, mismatched
// int and Return (foo::*)(ArgTypes...).
foo1.print3(3); // Error: int isn't a pointer-to-member, can't be used with "->*".
And so on...
Of these options, print3() consistently gives the cleanest error messages when misused, making it the best option when everything else is equal. print2b() gives cleaner error messages when called with the wrong number of parameters, but otherwise matches print2a().
Summary:
There are three ways to take a pointer-to-member-function, as described above:
Declare it manually, as described in other answers.
void const foo::print(void const (foo::* f)());
Use templates to specialise it, and take any parameters it might need.
template<typename Return, typename... ArgTypes>
void const foo::print(Return (foo::* f)(ArgTypes...), ArgTypes... args);
Or...
template<typename Return, typename... ArgTypes, typename... Args>
void const foo::print(Return (foo::* f)(ArgTypes...), Args... args);
Take the function as a template parameter, and any parameters it may need.
template<typename MemberFunction, typename... Args>
void const foo::print(MemberFunction f, Args... args);
Of these:
The first option gives you the most control over which functions print() is allowed to take, but requires you to explicitly overload it for each type of pointer-to-member-function you want to allow (e.g. void (foo::*)() or int (foo::*)(int, int)); this makes it the least future-proof, because you need to update the function if you add new functions to foo and want it to take them.
The second and third options, conversely, are future-proof, and will take any pointer-to-member-function. However, they don't allow you to restrict what kind of member function you pass, unless you put extra effort into it.
If used incorrectly, the third option will give the cleanest error message, which is useful when troubleshooting. Conversely, the first option will usually emit a conversion error, and the second option will usually emit a "can't deduce template parameters" error. If called with a member function that takes parameters, when not supplied with those parameters, both the third option and the second version of the second option will give the correct error; the third option will emit a cleaner, easier-to-read error, however.

Related

C++ constraints on variadic template arguments

I stumbled upon this code in the SerenityOS project:
template<typename... Parameters>
void dbgln(CheckedFormatString<Parameters...>&& fmtstr, const Parameters&... parameters)
They are re-implementing an equivalent of println! from rust. An easier version of printf where you don't need to care about the argument type and is used this way:
dbgln("This is a {}", "test");
They are doing some compile time checks on the fmtstr making sure that there are no unclosed braces and that the number of braces match the number of arguments. That's why the FormatString struct need to be templated to have access to the number of argument at compile time.
But there is something I don't understand. I wrote an MWE with the code below which, in essence, reproduce what they are doing:
#include <stddef.h>
template<typename... Args>
void compiletime_fail(Args...);
template<typename ...Parameters>
struct UnconstrainedFormatString {
template <size_t size>
consteval UnconstrainedFormatString(const char (&buffer)[size]): m_buffer(buffer), m_size(size) {
}
const char *m_buffer { nullptr };
const size_t m_size { 0 };
};
template<typename T>
struct __IdentityType {
using Type = T;
};
template<typename T>
using IdentityType = typename __IdentityType<T>::Type;
template<typename... Args>
using FormatString = UnconstrainedFormatString<IdentityType<Args>...>; // but why?
template<typename ...Parameters>
constexpr void println(FormatString<Parameters...>&& fmtstr, const Parameters& ...parameters) {
}
int main() {
println("this is a test", 1, 2, 3);
}
if I used UnconstrainedFormatString in the println signature I get this error from the compiler:
/cplayground/code.cpp:32:3: error: no matching function for call to 'println'
println("this is a test", 1, 2, 3);
^~~~~~~
/cplayground/code.cpp:28:16: note: candidate template ignored: could not match 'UnconstrainedFormatString<type-parameter-0-0...>' against 'char const[15]'
constexpr void println(UnconstrainedFormatString<Parameters...>&& fmtstr, const Parameters& ...parameters) {
In order for it to compile, I need to do that funky business with IdentityType.
Why do I need this?
See the https://en.cppreference.com/w/cpp/language/template_argument_deduction#Implicit_conversions :
Type deduction does not consider implicit conversions (other than type
adjustments listed above): that's the job for overload resolution,
which happens later.
How does the FormatString/IdentityType change things? The IdentityType suppresses the deduction of template parameters for const char[N] and now the string is used as a constructor parameter for UnconstrainedFormatString<...>.
You can learn more details here:
https://humanreadablemag.com/issues/0/articles/how-to-avoid-template-type-deduction-in-c
When you use UnconstrainedFormatString only, the compiler tries to deduct UnconstrainedFormatString from const char [N] and fails since for templates it "doesn't know" that the conversion from const char[N] to UnconstrainedFormatString exists.
You can easily check with the
println(UnconstrainedFormatString<int, int, int>("test"), 1, 2, 3);
Since no conversion is needed here, it works, as well.

Variadic template function parameters and reference type deduction

I'm missing something very fundamental about type deduction here:
I'm attempting to write a wrapper function that calls a writer function with a nullptr to get a required length, then resizes a buffer, then calls the function again, now with the resized buffer, to get the final output. There's a large number of these writer functions, and I want to generalize the call/resize/call pattern into a variadic template function.
However, I'm stuck at trying to pass both a function pointer to a function taking the variadic args, and passing the variadic args, when any parameter in the list is a const reference:
static void val_arg(int) { }
static void ref_arg(const int&) { }
template <typename... Args>
static void helper(void (*fun)(Args...), Args... args)
{
(*fun)(args...);
}
void proxy(const int& arg)
{
helper(&val_arg, arg); // Fine
helper(&ref_arg, arg); // 'void helper(void (__cdecl *)(Args...),Args...)': template parameter 'Args' is ambiguous
// note: could be 'const int&'
// note: or 'int'
}
void test()
{
proxy(1); // Force 1 to be const int&
}
What can I do to make it transparently accept both cases? Why is it not acknowledging that the function passed in accepts a const ref, and the argument to the proxy is also a const ref?
Args... won't deduce a reference type.
template <typename Fun, typename... Args>
static void helper(Fun fun, Args&&... args)
{
fun(std::forward<Args>(args)...);
}

Template type deduction for a pointer to member function

I have a very similar problem to that presented by Morpheus, in the following question:
Overloaded member function pointer to template
The solution proposed by Richard Corden requires the user to explicitly specify the function parameter type, to distinguish it among the overloads. However, this solution does not seem to work with overloads with a varying number of arguments of the same type.
Consider this example (derived from the original question):
template <typename T>
class A
{
public:
template<class Arg1>
void connect(void (T::*f)(Arg1))
{
//Do some stuff
}
template<class Arg1, class Arg2>
void connect(void (T::*f)(Arg1,Arg2))
{
//Do some stuff
}
void connect(void (T::*f)())
{
//Do some stuff
}
};
class GApp
{
public:
void foo() {}
void foo(double d) {}
void foo(double d1, double d2) {}
};
int main ()
{
A<GApp> a;
a.connect (&GApp::foo); // foo () - OK
a.connect<double> (&GApp::foo); // foo (double) - FAIL
a.connect<double,double> (&GApp::foo); // foo (double,double) - OK
}
GNU G++ 3.4.5 and MSVC 2008 do not compile the code above, both presenting similar error messages:
test.cpp: In function `int main()':
test.cpp:36: error: call of overloaded `connect(<unknown type>)' is ambiguous
test.cpp:7: note: candidates are: void A<T>::connect(void (T::*)(Arg1)) [with Arg1 = double, T = GApp]
test3.cpp:13: note: void A<T>::connect(void (T::*)(Arg1, Arg2)) [with Arg1 = double, Arg2 = double, T = GApp]
I'm aware of some workarounds that can make it compile, like assigning the pointer to a variable of the exact same type (e.g. void (GApp::*tmp)(double) = &GApp::foo;) or, using a more explicity form when calling the connect function (e.g. connect((void (GApp::*)(double))(&GApp::foo));).
However, I prefer the first solution and would like to know why it is not working.
Thank you in advance!
For a.connect<double> (&GApp::foo), both the foo(double) and foo(double, double) will match the overload of connect with one, and with two template parameters respectively (in the case of the two parameter version, the second template argument will be deduced, the first argument was provided by you explicitly).
If you want to disambiguate ambiguous cases, I recommend that you pass the exact type, so no surprises can happen. Instead of those overloads, why not have a single overload
template<typename MType, typename T>
void connect(MType T::*f)
{
//Do some stuff
}
a.connect<void()> (&GApp::foo);
a.connect<void(double)> (&GApp::foo);
a.connect<void(double, double)> (&GApp::foo);
The last call to connect should work fine in your code too. You then can dissect the type MType in connect with separate templates, to get the parameter and return types.
The problem with the original code is that you are explicitly defining the wrong part. When you specify a list of template parameters, even when you specify one, the compiler will attempt to deduce the second one and then it runs right back into ambiguity because it doesn't know if you want to use (double,double) or (double) variation.
Instead of defining template parameters, let the compiler deduce them but explicitly specify which one of the foo() functions you want to use:
int main()
{
A<GApp> a;
a.connect (&GApp::foo); // foo () - OK
a.connect( ( void (GApp::*)(double) )&GApp::foo); // foo (double) - OK
a.connect( ( void (GApp::*)(double, double) ) &GApp::foo); // foo (double,double) - OK
}

Nested bind expressions

This is a followup question to my previous question.
#include <functional>
int foo(void) {return 2;}
class bar {
public:
int operator() (void) {return 3;};
int something(int a) {return a;};
};
template <class C> auto func(C&& c) -> decltype(c()) { return c(); }
template <class C> int doit(C&& c) { return c();}
template <class C> void func_wrapper(C&& c) { func( std::bind(doit<C>, std::forward<C>(c)) ); }
int main(int argc, char* argv[])
{
// call with a function pointer
func(foo);
func_wrapper(foo); // error
// call with a member function
bar b;
func(b);
func_wrapper(b);
// call with a bind expression
func(std::bind(&bar::something, b, 42));
func_wrapper(std::bind(&bar::something, b, 42)); // error
// call with a lambda expression
func( [](void)->int {return 42;} );
func_wrapper( [](void)->int {return 42;} );
return 0;
}
I'm getting a compile errors deep in the C++ headers:
functional:1137: error: invalid initialization of reference of type ‘int (&)()’ from expression of type ‘int (*)()’
functional:1137: error: conversion from ‘int’ to non-scalar type ‘std::_Bind<std::_Mem_fn<int (bar::*)(int)>(bar, int)>’ requested
func_wrapper(foo) is supposed to execute func(doit(foo)). In the real code it packages the function for a thread to execute. func would the function executed by the other thread, doit sits in between to check for unhandled exceptions and to clean up. But the additional bind in func_wrapper messes things up...
At the beginning, please let me introduce 2 key points:
a: When using nested std::bind, the inner std::bind is evaluated first, and the return value will be substituted in its place while the outer std::bind is evaluated. That means std::bind(f, std::bind(g, _1))(x) executes as same as f(g(x)) does. The inner std::bind is supposed to be wrapped by std::ref if the outer std::bind wants a functor rather than a return value.
b: The r-value reference cannot be correctly forwarded to the function by using std::bind. And the reason has already been illustrated in detail.
So, let's look at the question. The most importance function here might be func_wrapper which is intended to perform 3 purposes:
Perfect forwarding a functor to doit function template at first,
then using std::bind to make doit as a closure,
and letting func function template execute the functor returned by std::bind at last.
According to point b, purpose 1 cannot be fulfilled. So, let's forget perfect forwarding and doit function template has to accept a l-value reference parameter.
According to point a, purpose 2 will be performed by using std::ref.
As a result, the final version might be:
#include <functional>
int foo(void) {return 2;}
class bar {
public:
int operator() (void) {return 3;};
int something(int a) {return a;};
};
template <class C> auto func(C&& c) -> decltype(c()) { return c(); }
template <class C> int doit(C&/*&*/ c) // r-value reference can't be forwarded via std::bind
{
return c();
}
template <class C> void func_wrapper(C&& c)
{
func(std::bind(doit<C>,
/* std::forward<C>(c) */ // forget pefect forwarding while using std::bind
std::ref(c)) // try to pass the functor itsself instead of its return value
);
}
int main(int argc, char* argv[])
{
// call with a function pointer
func(foo);
func_wrapper(foo); // error disappears
// call with a member function
bar b;
func(b);
func_wrapper(b);
// call with a bind expression
func(std::bind(&bar::something, b, 42));
func_wrapper(std::bind(&bar::something, b, 42)); // error disappears
// call with a lambda expression
func( [](void)->int {return 42;} );
func_wrapper( [](void)->int {return 42;} );
return 0;
}
But, if you really want to achieve purpose 1 and 2, how? Try this:
#include <functional>
#include <iostream>
void foo()
{
}
struct bar {
void operator()() {}
void dosomething() {}
};
static bar b;
template <typename Executor>
void run(Executor&& e)
{
std::cout << "r-value reference forwarded\n";
e();
}
template <typename Executor>
void run(Executor& e)
{
std::cout << "l-value reference forwarded\n";
e();
}
template <typename Executor>
auto func(Executor&& e) -> decltype(e())
{
return e();
}
template <bool b>
struct dispatcher_traits {
enum { value = b };
};
template <typename Executor, bool is_lvalue_reference>
class dispatcher {
private:
static void dispatch(Executor& e, dispatcher_traits<true>)
{
run(e);
}
static void dispatch(Executor& e, dispatcher_traits<false>)
{
run(std::ref(e));
}
public:
static void forward(Executor& e)
{
dispatch(e, dispatcher_traits<is_lvalue_reference>());
}
};
template <typename Executor>
void func_wrapper(Executor&& e)
{
typedef dispatcher<Executor,
std::is_lvalue_reference<Executor>::value>
dispatcher_type;
func(std::bind(&dispatcher_type::forward, std::ref(e)));
}
int main()
{
func_wrapper(foo); // l-value
func_wrapper(b); // l-value
func_wrapper(bar()); // r-value
func_wrapper(std::bind(&bar::dosomething, &b)); // r-value
func_wrapper([](){}); // r-value
}
Let me explain some points:
To reduce lots of return statements, changing functor signature from int() to void().
The 2 run() function templates are used to check whether the original functor parameter is perfect forwarded or not.
dispatcher_traits is going to map bool constant to type.
You'd better name dispatcher::forward to differ from dispatcher::dispatch or you have to invoke std::bind template with dispatcher::forward's signature.
Looking at this the second time now, and I think I have a plausable explanation for the first error you are seeing.
In this case, it's more helpful to look at the complete error and the template instantiations that lead up to it. The error printed by my compiler (GCC 4.4), for example, ends with the following lines:
test.cpp:12: instantiated from ‘decltype (c()) func(C&&) [with C = std::_Bind<int (*(int (*)()))(int (&)())>]’
test.cpp:16: instantiated from ‘void func_wrapper(C&&) [with C = int (&)()]’
test.cpp:22: instantiated from here
/usr/include/c++/4.4/tr1_impl/functional:1137: error: invalid initialization of reference of type ‘int (&)()’ from expression of type ‘int (*)()’
Now looking at this bottom-up, the actual error message seems correct; the types the compiler has deduced are incompatible.
The first template instantiation, at func_wrapper, clearly shows what type the compiler has deduced from the actual parameter foo in func_wrapper(foo). I personally expected this to be a function pointer, but it is in fact a function reference.
The second template instantiation is hardly readable. But messing around with std::bind a bit, I learned that the format of the textual representation GCC prints for a bind functor is roughly:
std::_Bind<RETURN-TYPE (*(BOUND-VALUE-TYPES))(TARGET-PARAMETER-TYPES)>
So tearing it apart:
std::_Bind<int (*(int (*)()))(int (&)())>
// Return type: int
// Bound value types: int (*)()
// Target parameter types: int (&)()
This is where the incompatible types start. Apparently, even though c in func_wrapper is a function reference, it turns into a function pointer once passed to std::bind, resulting in the type incompatibility. For what it's worth, std::forward doesn't matter at all in this case.
My reasoning here is that std::bind only seems to care about values, and not references. In C/C++, there's no such thing as a function value; there's only references and pointers. So when the function reference is dereferenced, the compiler can only meaningfully give you a function pointer.
The only control you have over this is your template parameters. You will have to tell the compiler that you're dealing with a function pointer from the start to make this work. It's probably what you had in mind anyways. To do that, explicitly specify the type you want for the template parameter C:
func_wrapper<int (*)()>(foo);
Or the more brief solution, explicitly take the function's address:
func_wrapper(&foo); // with C = int (*)()
I'll get back to you if I ever figure out the second error. :)

Can you use keyword explicit to prevent automatic conversion of method parameters?

I know you can use C++ keyword 'explicit' for constructors of classes to prevent an automatic conversion of type. Can you use this same command to prevent the conversion of parameters for a class method?
I have two class members, one which takes a bool as a param, the other an unsigned int. When I called the function with an int, the compiler converted the param to a bool and called the wrong method. I know eventually I'll replace the bool, but for now don't want to break the other routines as this new routine is developed.
No, you can't use explicit, but you can use a templated function to catch the incorrect parameter types.
With C++11, you can declare the templated function as deleted. Here is a simple example:
#include <iostream>
struct Thing {
void Foo(int value) {
std::cout << "Foo: value" << std::endl;
}
template <typename T>
void Foo(T value) = delete;
};
This gives the following error message if you try to call Thing::Foo with a size_t parameter:
error: use of deleted function
‘void Thing::Foo(T) [with T = long unsigned int]’
In pre-C++11 code, it can be accomplished using an undefined private function instead.
class ClassThatOnlyTakesBoolsAndUIntsAsArguments
{
public:
// Assume definitions for these exist elsewhere
void Method(bool arg1);
void Method(unsigned int arg1);
// Below just an example showing how to do the same thing with more arguments
void MethodWithMoreParms(bool arg1, SomeType& arg2);
void MethodWithMoreParms(unsigned int arg1, SomeType& arg2);
private:
// You can leave these undefined
template<typename T>
void Method(T arg1);
// Below just an example showing how to do the same thing with more arguments
template<typename T>
void MethodWithMoreParms(T arg1, SomeType& arg2);
};
The disadvantage is that the code and the error message are less clear in this case, so the C++11 option should be selected whenever available.
Repeat this pattern for every method that takes the bool or unsigned int. Do not provide an implementation for the templatized version of the method.
This will force the user to always explicitly call the bool or unsigned int version.
Any attempt to call Method with a type other than bool or unsigned int will fail to compile because the member is private, subject to the standard exceptions to visibility rules, of course (friend, internal calls, etc.). If something that does have access calls the private method, you will get a linker error.
No. explicit prevents automatic conversion between specific classes, irrespective of context. And of course you can't do it for built-in classes.
The following is a very basic wrapper that can be used to create a strong typedef:
template <typename V, class D>
class StrongType
{
public:
inline explicit StrongType(V const &v)
: m_v(v)
{}
inline operator V () const
{
return m_v;
}
private:
V m_v; // use V as "inner" type
};
class Tag1;
typedef StrongType<int, Tag1> Tag1Type;
void b1 (Tag1Type);
void b2 (int i)
{
b1 (Tag1Type (i));
b1 (i); // Error
}
One nice feature of this approach, is that you can also distinguish between different parameters with the same type. For example you could have the following:
class WidthTag;
typedef StrongType<int, WidthTag> Width;
class HeightTag;
typedef StrongType<int, HeightTag> Height;
void foo (Width width, Height height);
It will be clear to the clients of 'foo' which argument is which.
Something that might work for you is to use templates. The following shows the template function foo<>() being specialized for bool, unsigned int, and int. The main() function shows how the calls get resolved. Note that the calls that use a constant int that don't specify a type suffix will resolve to foo<int>(), so you'll get an error calling foo( 1) if you don't specialize on int. If this is the case, callers using a literal integer constant will have to use the "U" suffix to get the call to resolve (this might be the behavior you want).
Otherwise you'll have to specialize on int and use the "U" suffix or cast it to an unsigned int before passing it on to the unsigned int version (or maybe do an assert that the value isn't negative, if that's what you want).
#include <stdio.h>
template <typename T>
void foo( T);
template <>
void foo<bool>( bool x)
{
printf( "foo( bool)\n");
}
template <>
void foo<unsigned int>( unsigned int x)
{
printf( "foo( unsigned int)\n");
}
template <>
void foo<int>( int x)
{
printf( "foo( int)\n");
}
int main ()
{
foo( true);
foo( false);
foo( static_cast<unsigned int>( 0));
foo( 0U);
foo( 1U);
foo( 2U);
foo( 0);
foo( 1);
foo( 2);
}
The currently accepted answer (using a private templated function) is nice, but outdated. With C++11, we can use deleted functions instead:
#include <iostream>
struct Thing {
void Foo(int value) {
std::cout << "Foo: value" << std::endl;
}
template <typename T>
void Foo(T value) = delete;
};
int main() {
Thing t;
int int_value = 1;
size_t size_t_value = 2;
t.Foo(int_value);
// t.Foo(size_t_value); // fails with below error
// error: use of deleted function
// ‘void Thing::Foo(T) [with T = long unsigned int]’
return 0;
}
This conveys the intent of the source code more directly and supplies the user with a clearer error message when trying to use the function with disallowed parameter types.
Compiler gave "ambiguous call" warning, which will be sufficient.
I was doing TDD development and didn't realize I forgot to implement the corresponding call in the mock object.
bool IS an int that is limited to either 0 or 1. That is the whole concept of return 0;, it is logically the same as saying return false;(don't use this in code though).
You could also write an int version that calls the bool one.