Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Function versus pointer to function, in context of std::function,huh?

Reply
Thread Tools

Function versus pointer to function, in context of std::function,huh?

 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      07-25-2011
When I do this:

typedef function< void( Type const& ) > DestroyFunc;

then Visual C++ 10.0 is happy.

But when I do this:

typedef function< void(*)( Type const& ) > DestroyFunc;

then it spews out a long sequence of silly error messages, like


<sillyErrorMessages>
1>c:\program files (x86)\microsoft visual studio
10.0\vc\include\functional(94): error C2027: use of undefined type
'std::tr1::_Get_function_impl<_Tx>'
1> with
1> [
1> _Tx=void (__cdecl *)(const int &)
1> ]
1> d:\dev\utility\clear_rounded_corners\cppx\owned.h( 35) : see
reference to class template instantiation 'std::tr1::function<_Fty>'
being compiled
1> with
1> [
1> _Fty=void (__cdecl *)(const int &)
1> ]
1> d:\dev\utility\clear_rounded_corners\main.cpp(283) : see
reference to class template instantiation 'cppx::Owned<Type>' being compiled
1> with
1> [
1> Type=int
1> ]
1>c:\program files (x86)\microsoft visual studio
10.0\vc\include\functional(95): error C2504: '_Type' : base class undefined
1>c:\program files (x86)\microsoft visual studio
10.0\vc\include\functional(9: error C2027: use of undefined type
'std::tr1::_Get_function_impl<_Tx>'
1> with
1> [
1> _Tx=void (__cdecl *)(const int &)
1> ]
1>c:\program files (x86)\microsoft visual studio
10.0\vc\include\functional(9: error C2146: syntax error : missing ';'
before identifier '_Mybase'
1>c:\program files (x86)\microsoft visual studio
10.0\vc\include\functional(9: error C4430: missing type specifier -
int assumed. Note: C++ does not support default-int
1>c:\program files (x86)\microsoft visual studio
10.0\vc\include\functional(9: error C4430: missing type specifier -
int assumed. Note: C++ does not support default-int
</sillyErrorMessages>


What? Isn't that function type decaying to pointer to function type? And
if it isn't, shouldn't std::function be able to tackle pointer to
function type?


Cheers, & just wondering,

- Alf
 
Reply With Quote
 
 
 
 
Noah Roberts
Guest
Posts: n/a
 
      07-25-2011
On 7/25/2011 5:50 AM, Alf P. Steinbach wrote:
> When I do this:
>
> typedef function< void( Type const& ) > DestroyFunc;
>
> then Visual C++ 10.0 is happy.
>
> But when I do this:
>
> typedef function< void(*)( Type const& ) > DestroyFunc;
>
> then it spews out a long sequence of silly error messages, like
>

....
> What? Isn't that function type decaying to pointer to function type?


Nope.

And
> if it isn't, shouldn't std::function be able to tackle pointer to
> function type?


void whatever(Type const&);

function<void(Type const&)> fun = &whatever;
 
Reply With Quote
 
 
 
 
SG
Guest
Posts: n/a
 
      07-26-2011
On 25 Jul., 14:50, Alf P. Steinbach wrote:
> When I do this:
>
> * *typedef function< void( Type const& ) > DestroyFunc;
>
> then Visual C++ 10.0 is happy.


Right. The function template is declared/defined like this:

template<class Signature>
class function; // intentionally undefined

template<class Ret, class...Params>
class function<Ret(Params...)> {
...
};

So, in your case, Ret=void and Params...=Type const&

> But when I do this:
>
> * *typedef function< void(*)( Type const& ) > DestroyFunc;
>
> then it spews out a long sequence of silly error messages, like


Yes. This partial specialization from above does not apply and the
primary template is undefined. That's why you get the error. You
passed a T* instead of a R(P...) type with T = void(Type const&).

> What? Isn't that function type decaying to pointer to function type?


There is no specialization for function pointer types. And types don't
decay. Just expressions do. The template parameter is supposed to be a
"signature" (return type and parameters).

> And
> if it isn't, shouldn't std::function be able to tackle pointer to
> function type?


Not as its template parameter, no. Why should it?

Cheers!
SG
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      07-26-2011
On 26.07.2011 10:33, SG wrote:
> On 25 Jul., 14:50, Alf P. Steinbach wrote:
>
>> ..., shouldn't std::function be able to tackle pointer to
>> function type?

>
> Not as its template parameter, no. Why should it?


For usability.

Lots of function types are defined by libraries.

Usually, I dare say nearly always, as pointer to function.

With current limitations, instead of

function< WNDPROC >

I probably have to write something like

function< decltype( *(WNDPROC()) ) >

or whatever the syntax is for decltype, but anyway, why should the
programmer have to write that when the template could/should do it?


Cheers, & thanks,

- Alf


 
Reply With Quote
 
Qi
Guest
Posts: n/a
 
      07-26-2011
On 2011-7-26 16:48, Alf P. Steinbach wrote:
> I probably have to write something like
>
> function< decltype( *(WNDPROC()) ) >
>
> or whatever the syntax is for decltype, but anyway, why should the
> programmer have to write that when the template could/should do it?


Or you can write some wrapper template

// not compiled code
template <typename T>
struct FunctionType
{
typedef boost::function<T> Result;
};

template <typename T>
struct FunctionType <T *>
{
typedef boost::function<T> Result;
};

Or don't use specialization, remove pointer in first template.

But why do you want to use boost::function?
I won't use a function object wrapper that can't use member
function directly. (bind? no...)


--
WQ

 
Reply With Quote
 
SG
Guest
Posts: n/a
 
      07-26-2011
On 26 Jul., 10:48, Alf P. Steinbach wrote:
> [...]
> I probably have to write something like
>
> * *function< decltype( *(WNDPROC()) ) >
>
> or whatever the syntax is for decltype,


*(WNDPROC()) is not a name but an lvalue expression referring to a
function. As such, decltype is forced to yield an lvalue-reference-to-
function type which is also not viable as template parameter for
std::function<>.

> but anyway, why should the
> programmer have to write that when the template could/should do it?


I don't see the value in this. You'd end up with distinct but
equivalent types with the exact same purpose. In your case:
function<void(*)()> and function<void()>. I would prefer transforming
the type before it's used as template parameter for function<>. But
that's just me.

SG
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      07-26-2011
On 26.07.2011 14:39, SG wrote:
> On 26 Jul., 10:48, Alf P. Steinbach wrote:
>> [...]
>> I probably have to write something like
>>
>> function< decltype( *(WNDPROC()) )>
>>
>> or whatever the syntax is for decltype,

>
> *(WNDPROC()) is not a name but an lvalue expression referring to a
> function. As such, decltype is forced to yield an lvalue-reference-to-
> function type which is also not viable as template parameter for
> std::function<>.


That sounds rather impractical and at odds with the usual "reference
can't be detected".

I haven't checked but assume you're right.

I also assume that good old `typeof` (from e.g. g++) was more practical.

I'm just starting to use the C++0x stuff, it doesn't seem that
well-designed.

So, does one have to use some template stuff like
PointeeType<WndProc>::T, where a reader of code must look elsewhere for
definition, or can decltype be brought into service via some proper
black magic incantantion?


>> but anyway, why should the
>> programmer have to write that when the template could/should do it?

>
> I don't see the value in this. You'd end up with distinct but
> equivalent types with the exact same purpose. In your case:
> function<void(*)()> and function<void()>.


You mention that as if it were some kind of problem?

What problem do you see with that?

Since we're dealing with such equivalence in practice anyway, e.g. decay
to pointer type everywhere a function type is used as formal argument
type, I really don't see any problem.


> I would prefer transforming
> the type before it's used as template parameter for function<>. But
> that's just me.


No, it's probably not just you. There is a kind of fad of reversing the
principle of least redundancy. Of writing as many ungrokkable technical
details up front as possible, repeated each place instead of being
centralized somewhere, in order to make the code look less clear; a sort
of misguided and almost feminine attempt to *look* technical.


Cheers,

- Alf
 
Reply With Quote
 
Noah Roberts
Guest
Posts: n/a
 
      07-26-2011
On 7/26/2011 3:08 AM, Qi wrote:
> On 2011-7-26 16:48, Alf P. Steinbach wrote:
> > I probably have to write something like
> >
> > function< decltype( *(WNDPROC()) ) >
> >
> > or whatever the syntax is for decltype, but anyway, why should the
> > programmer have to write that when the template could/should do it?

>
> Or you can write some wrapper template
>
> // not compiled code
> template <typename T>
> struct FunctionType
> {
> typedef boost::function<T> Result;
> };
>
> template <typename T>
> struct FunctionType <T *>
> {
> typedef boost::function<T> Result;
> };


Or

template < typename T >
struct FunctionType<T*>
: FunctionType<typename std::remove_const<T>::type>
{};

template < typename T >
struct FunctionType<T&>
: FunctionType<typename std::remove_const<T>::type>
{};

I believe this would remove any pointer or reference appendages, no
matter how deep, and construct a function type out of whatever you pass in.
 
Reply With Quote
 
SG
Guest
Posts: n/a
 
      07-26-2011
On 26 Jul., 17:49, Alf P. Steinbach wrote:
> On 26.07.2011 14:39, SG wrote:
> > *(WNDPROC()) is not a name but an lvalue expression referring to a
> > function. As such, decltype is forced to yield an lvalue-reference-to-
> > function type which is also not viable as template parameter for
> > std::function<>.

>
> That sounds rather impractical and at odds with the usual "reference
> can't be detected".


It's more powerful than typeof.

> I also assume that good old `typeof` (from e.g. g++) was more practical.


I agree that in many cases the behaviour of the typeof extension is
all you need. And in some cases it won't. (Think of how to implement
result_of<>). I expect to see many decltype uses similar to this:

template<class T, class U>
auto operator*(vec3<T> const& v, U s) -> vec3<decltype(p[0]*s)>;

where replacing decltype with typeof ought not to make a difference.
And if you really need the typeof behaviour very often, you may use
this shortcut:

#include <type_traits>
#define TYPEOF(xpr) typename std::decay<decltype(xpr)>::type

Since C++2011 allows the typename keyword to appear in more contexts
(including non-template ones) this macro should just work everywhere.

> I'm just starting to use the C++0x stuff,
> it doesn't seem that well-designed.


There are some little warts here and there, but all in all I'm very
happy with how things turned out.

> So, does one have to use some template stuff like
> PointeeType<WndProc>::T, where a reader of code must look elsewhere for
> definition, or can decltype be brought into service via some proper
> black magic incantantion?


I don't think so.

> >> but anyway, why should the
> >> programmer have to write that when the template could/should do it?

>
> > I don't see the value in this. You'd end up with distinct but
> > equivalent types with the exact same purpose. In your case:
> > function<void(*)()> *and function<void()>.

>
> You mention that as if it were some kind of problem?
> What problem do you see with that?


It's the principle of the matter. You end up with two different types
that could have been one. It complicates things. Will a
function<void(*)()> be convertible to a function<void()> and/or the
other way around? If not why not? Also, the types are not reference-
compatible.

> Since we're dealing with such equivalence in practice anyway, e.g. decay
> to pointer type everywhere a function type is used as formal argument
> type, I really don't see any problem.


I really don't see any advantage. And I really don't like the let's-
just-use-two-distinct-types-for-the-same-thing strategy. :-p

If you hate his so much you could write a proposal to give
std::function some other implementation-defined name (i.e.
std::_function_) and to create a type-transforming alias that emulates
this decay for types:

template<class T> struct aftt_ { typedef T type; };
template<class T> struct aftt_<T*> : aftt_<T> {};
template<class T> struct aftt_<T&> : aftt_<T> {};
template<class T> using function = _function_<typename
aftt_<T>::type>;

With this, function<void()> and function<void(*)()> would be
synonymous with _function_<void()> and all these names would refer to
exactly one type (and we both can live in peace).

> [...opinion...]


That's yours. I have mine.

Cheers!
SG
 
Reply With Quote
 
Qi
Guest
Posts: n/a
 
      07-27-2011
On 2011-7-27 2:21, SG wrote:

>>> I don't see the value in this. You'd end up with distinct but
>>> equivalent types with the exact same purpose. In your case:
>>> function<void(*)()> and function<void()>.


The problem is, boost::function already supports two syntax.

Preferred syntax
boost::function<float (int x, int y)> f;

Portable syntax
boost::function2<float, int, int> f;

If it only supports first syntax, we can say it's how
it works and won't complain that it doesn't supports
function pointer syntax.

But since it already supports the two syntax, I can't see
why it doesn't supports the function pointer syntax, which
is more common accepted than function type, IMHO.

Of course it's the library provider's choice, so I won't
complain more (and I don't use boost::function).


--
WQ
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
const pointer versus const content pointed to by pointer Disc Magnet C Programming 1 05-06-2010 10:27 AM
Re: Mozilla versus IE versus Opera versus Safari Peter Potamus the Purple Hippo Firefox 0 05-08-2008 12:56 PM
equal? versus eql? versus == versus === verus <=> Paul Butcher Ruby 12 11-28-2007 06:06 AM
List context versus list context Bo Lindbergh Perl Misc 12 06-28-2006 07:12 PM
function pointer and member function pointer question glen stark C++ 2 10-10-2003 01:41 PM



Advertisments