473,394 Members | 1,866 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

function pointes and templates

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
14 1633
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
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


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


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
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
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
>
This is why functors are generaly passed by value.


Thanks, I'll remember the advice.

john
Jul 22 '05 #8
>
This is why functors are generaly passed by value.


Thanks, I'll remember the advice.

john
Jul 22 '05 #9
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
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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

14
by: John Harrison | last post by:
Can anyone explain why this code fails to compile? #include <iostream> void func() { std::cout << "success!\n"; } struct S
11
by: lokb | last post by:
Hi, I have a structure which and defined a smart pointer to the structure. /* Structure of Begin Document Index Record */ typedef struct BDI_Struct{ unsigned char rname; unsigned short int...
5
by: Levent | last post by:
Hi, Why doesn't this work? (tried with gcc 3.3.3 and VC++ 7.1): #include <iostream> template<class T, unsigned N> struct Foo { void func(); }; template<class T, unsigned N>
16
by: WittyGuy | last post by:
Hi, What is the major difference between function overloading and function templates? Thanks! http://www.gotw.ca/resources/clcm.htm for info about ]
42
by: baumann | last post by:
hi all, typedef int (*pfunc)(int , int); pfunc a_func; i know it's ok, but how can define a_func without typedef statement? thanks .
6
by: wkaras | last post by:
I tried a couple of compilers, and both gave errors compiling this: template <bool fin, typename T> T foo(T val); template <typename T> T foo<true, T>(T val) { return(val); } But both gave...
2
by: recover | last post by:
#include <stdio.h> template<class T> class TpHello { public: int GetHash(){return 0;} protected: private: T a;
5
by: desktop | last post by:
I have this example: template<class T(1) void f( T ); template<class T(2) void f( T* ); template< (3)
4
by: nickyspace | last post by:
HI all I have a little issue with this php code. Below is the code CODE: PHP 1.<?
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.