By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,760 Members | 1,557 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,760 IT Pros & Developers. It's quick & easy.

function pointes and templates

P: n/a
Can anyone explain why this code fails to compile?

#include <iostream>

void func()
{
std::cout << "success!\n";
}

struct S
{
template <class F>
void method(const F& f)
{
f();
}
};

int main()
{
S s;
s.method(func);
}

but with a very slight change to main

int main()
{
S s;
s.method(&func); // change here
}

it compiles and works.

john
Jul 22 '05 #1
Share this Question
Share on Google+
14 Replies


P: n/a
On Tue, 6 Apr 2004 18:19:19 +0100, "John Harrison"
<jo*************@hotmail.com> wrote:
Can anyone explain why this code fails to compile?


[snip]

Looks like a compiler bug. It works fine on mine.

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #2

P: n/a
On Tue, 6 Apr 2004 18:19:19 +0100, "John Harrison"
<jo*************@hotmail.com> wrote:
Can anyone explain why this code fails to compile?


[snip]

Looks like a compiler bug. It works fine on mine.

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #3

P: n/a


John Harrison wrote:
Can anyone explain why this code fails to compile?

#include <iostream>

void func()
{
std::cout << "success!\n";
}

struct S
{
template <class F>
void method(const F& f)
{
f();
}
};

int main()
{
S s;
s.method(func);
}

but with a very slight change to main

int main()
{
S s;
s.method(&func); // change here
}

it compiles and works.

john


I think it's because a function (not being an object) cannot be const,
as illustrated by this, which does compile on my system:

void f () { }

int main ()
{
typedef void (& func_t) ();

const func_t f = func;
func_t g = f; // If g's referent were really const this wouldn't work.
}

Therefore, you can't initialize a reference-to-const-T with a function,
since a function can be T but not const T.

The same is not true of a pointer-to-function.

--
Regards,
Buster.
Jul 22 '05 #4

P: n/a


John Harrison wrote:
Can anyone explain why this code fails to compile?

#include <iostream>

void func()
{
std::cout << "success!\n";
}

struct S
{
template <class F>
void method(const F& f)
{
f();
}
};

int main()
{
S s;
s.method(func);
}

but with a very slight change to main

int main()
{
S s;
s.method(&func); // change here
}

it compiles and works.

john


I think it's because a function (not being an object) cannot be const,
as illustrated by this, which does compile on my system:

void f () { }

int main ()
{
typedef void (& func_t) ();

const func_t f = func;
func_t g = f; // If g's referent were really const this wouldn't work.
}

Therefore, you can't initialize a reference-to-const-T with a function,
since a function can be T but not const T.

The same is not true of a pointer-to-function.

--
Regards,
Buster.
Jul 22 '05 #5

P: n/a
John Harrison wrote in news:c4*************@ID-196037.news.uni-berlin.de:
Can anyone explain why this code fails to compile?

#include <iostream>

void func()
{
std::cout << "success!\n";
}

struct S
{
template <class F>
void method(const F& f)
{
f();
}
};

int main()
{
S s;
s.method(func);
Both of these are ok:

s.method( static_cast< void (*)() >( func ) );
s.method( static_cast< void (&)() >( func ) );

Both conversion's are standard conversions and have equal rank (*).
Both require a futher qualification adjustment (add const).

*) Exact Match.

}

but with a very slight change to main

int main()
{
S s;
s.method(&func); // change here
}

it compiles and works.


There is no ambiguity, &func is a function pointer, only a
futher qaulification adjustment is required. There is no
ambiguos conversion to reference-to-function available.

This is why functors are generaly passed by value.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #6

P: n/a
John Harrison wrote in news:c4*************@ID-196037.news.uni-berlin.de:
Can anyone explain why this code fails to compile?

#include <iostream>

void func()
{
std::cout << "success!\n";
}

struct S
{
template <class F>
void method(const F& f)
{
f();
}
};

int main()
{
S s;
s.method(func);
Both of these are ok:

s.method( static_cast< void (*)() >( func ) );
s.method( static_cast< void (&)() >( func ) );

Both conversion's are standard conversions and have equal rank (*).
Both require a futher qualification adjustment (add const).

*) Exact Match.

}

but with a very slight change to main

int main()
{
S s;
s.method(&func); // change here
}

it compiles and works.


There is no ambiguity, &func is a function pointer, only a
futher qaulification adjustment is required. There is no
ambiguos conversion to reference-to-function available.

This is why functors are generaly passed by value.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #7

P: n/a
>
This is why functors are generaly passed by value.


Thanks, I'll remember the advice.

john
Jul 22 '05 #8

P: n/a
>
This is why functors are generaly passed by value.


Thanks, I'll remember the advice.

john
Jul 22 '05 #9

P: n/a
On 06 Apr 2004 18:56:13 GMT, Rob Williscroft
<rt*@freenet.REMOVE.co.uk> wrote:
Both of these are ok:

s.method( static_cast< void (*)() >( func ) );
s.method( static_cast< void (&)() >( func ) );

Both conversion's are standard conversions and have equal rank (*).
Both require a futher qualification adjustment (add const).

*) Exact Match.
Yes, but 14.8.2.1/2 says that during template argument deduction, if
the argument is a function type, it is replaced with the function
pointer type, so there is no possibility of your second version above
being deduced. This is a template argument deduction issue, not
overloading - there is only one function called func and one called
method.
}

but with a very slight change to main

int main()
{
S s;
s.method(&func); // change here
}

it compiles and works.


There is no ambiguity, &func is a function pointer, only a
futher qaulification adjustment is required. There is no
ambiguos conversion to reference-to-function available.

This is why functors are generaly passed by value.


There is no ambiguity anyway - Comeau and GCC compile the original
code fine, without the &.

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #10

P: n/a
On 06 Apr 2004 18:56:13 GMT, Rob Williscroft
<rt*@freenet.REMOVE.co.uk> wrote:
Both of these are ok:

s.method( static_cast< void (*)() >( func ) );
s.method( static_cast< void (&)() >( func ) );

Both conversion's are standard conversions and have equal rank (*).
Both require a futher qualification adjustment (add const).

*) Exact Match.
Yes, but 14.8.2.1/2 says that during template argument deduction, if
the argument is a function type, it is replaced with the function
pointer type, so there is no possibility of your second version above
being deduced. This is a template argument deduction issue, not
overloading - there is only one function called func and one called
method.
}

but with a very slight change to main

int main()
{
S s;
s.method(&func); // change here
}

it compiles and works.


There is no ambiguity, &func is a function pointer, only a
futher qaulification adjustment is required. There is no
ambiguos conversion to reference-to-function available.

This is why functors are generaly passed by value.


There is no ambiguity anyway - Comeau and GCC compile the original
code fine, without the &.

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #11

P: n/a
tom_usenet wrote in news:n8********************************@4ax.com:
Both of these are ok:

s.method( static_cast< void (*)() >( func ) );
s.method( static_cast< void (&)() >( func ) );

Both conversion's are standard conversions and have equal rank (*).
Both require a futher qualification adjustment (add const).

*) Exact Match.


Yes, but 14.8.2.1/2 says that during template argument deduction, if
the argument is a function type, it is replaced with the function
pointer type, so there is no possibility of your second version above
being deduced. This is a template argument deduction issue, not
overloading - there is only one function called func and one called
method.


1 Template argument deduction is done by comparing each function
template parameter type (call it P) with the type of the
corresponding argument of the call (call it A) as described below.

2 If P is not a reference type:

...

If A is a function type, the pointer type produced by the
function-to-pointer standard conversion (4.3) is used in
place of A for type deduction; otherwise,

...

I quoted (1) as it describes P.

Given:

struct S
{
template <class F>
void method(const F& f)
{
f();
}
};

You seem to think "template parameter type (call it P)" is F where as
I think it is F const &.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #12

P: n/a
tom_usenet wrote in news:n8********************************@4ax.com:
Both of these are ok:

s.method( static_cast< void (*)() >( func ) );
s.method( static_cast< void (&)() >( func ) );

Both conversion's are standard conversions and have equal rank (*).
Both require a futher qualification adjustment (add const).

*) Exact Match.


Yes, but 14.8.2.1/2 says that during template argument deduction, if
the argument is a function type, it is replaced with the function
pointer type, so there is no possibility of your second version above
being deduced. This is a template argument deduction issue, not
overloading - there is only one function called func and one called
method.


1 Template argument deduction is done by comparing each function
template parameter type (call it P) with the type of the
corresponding argument of the call (call it A) as described below.

2 If P is not a reference type:

...

If A is a function type, the pointer type produced by the
function-to-pointer standard conversion (4.3) is used in
place of A for type deduction; otherwise,

...

I quoted (1) as it describes P.

Given:

struct S
{
template <class F>
void method(const F& f)
{
f();
}
};

You seem to think "template parameter type (call it P)" is F where as
I think it is F const &.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #13

P: n/a
On 07 Apr 2004 14:06:18 GMT, Rob Williscroft
<rt*@freenet.REMOVE.co.uk> wrote:
tom_usenet wrote in news:n8********************************@4ax.com:
Both of these are ok:

s.method( static_cast< void (*)() >( func ) );
s.method( static_cast< void (&)() >( func ) );

Both conversion's are standard conversions and have equal rank (*).
Both require a futher qualification adjustment (add const).

*) Exact Match.
Yes, but 14.8.2.1/2 says that during template argument deduction, if
the argument is a function type, it is replaced with the function
pointer type, so there is no possibility of your second version above
being deduced. This is a template argument deduction issue, not
overloading - there is only one function called func and one called
method.


1 Template argument deduction is done by comparing each function
template parameter type (call it P) with the type of the
corresponding argument of the call (call it A) as described below.

2 If P is not a reference type:


Oops, I missed the "If P is not a reference type". In this case, P is
a reference type of course, so the paragraph below doesn't apply.

...

If A is a function type, the pointer type produced by the
function-to-pointer standard conversion (4.3) is used in
place of A for type deduction; otherwise,

...

I quoted (1) as it describes P.

Given:

struct S
{
template <class F>
void method(const F& f)
{
f();
}
};

You seem to think "template parameter type (call it P)" is F where as
I think it is F const &.


I just missed the "If P is not a reference type". So in fact, the
reverse is true; rather than choosing the function pointer type for
the template parameter, template argument deduction deduces F=void():

S::method<void()>

Still, as I said before, there is nothing ambiguous about it and
overload resolution doesn't come into it, since 1 function is chosen
by TAD (S::method<void()>) and there is only 1 valid conversion
sequence for the parameter to reach that type (void() ->
void(const&)() (direct reference binding).

The original example compiles fine with Comeau C++:

#include <iostream>
void func()
{ std::cout << "success!\n"; }
struct S
{
template <class F>
void method(const F& f)
{ f(); }
};
int main()
{
S s;
s.method(func);
}

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #14

P: n/a
tom_usenet wrote in news:ap********************************@4ax.com in
comp.lang.c++:
You seem to think "template parameter type (call it P)" is F where as
I think it is F const &.
I just missed the "If P is not a reference type". So in fact, the
reverse is true; rather than choosing the function pointer type for
the template parameter, template argument deduction deduces F=void():

S::method<void()>


Yep, I mistakenly assumed a conversion was nessacery for TAD, clearly
it isn't.

Still, as I said before, there is nothing ambiguous about it and
overload resolution doesn't come into it, since 1 function is chosen
by TAD (S::method<void()>) and there is only 1 valid conversion
sequence for the parameter to reach that type (void() ->
void(const&)() (direct reference binding).


Thanks for the update.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #15

This discussion thread is closed

Replies have been disabled for this discussion.