On May 25, 10:44 am, Barry <dhb2...@gmail.com> wrote:
On May 24, 10:28 pm, courp...@gmail.com wrote:
On 24 mai, 04:16, Barry <dhb2...@gmail.com> wrote:
a clean implementation of is_function from this NG a while ago:
by means of "function to pointer-to-function conversion"
typedef char (&yes) [1];
typedef char (&no) [2];
// is_class_type
template <typename T>
class is_class_type
{
template <typename S>
static yes check(int S::*);
template <typename S>
static no check(...);
public:
static bool const value = (sizeof(check<T>(0)) == sizeof(yes));
};
template <typename T>
class is_function
{
template <typename S>
static yes check(S*);
template <typename S>
static no check(...);
public:
static bool const value =
(!is_class_type<T>::value)
&&
(sizeof(check<T>(*(T*)(0))) == sizeof(yes));
};
I think the following should do the same thing but in a shorter way :
template < class T >
struct is_function {
enum { value = is_convertible<void(*)(T),void(*)(T*)>::value };
};
[------
Full working version without an "is_convertible" facility :
typedef char (&yes) [1];
typedef char (&no) [2];
template < class T >
struct is_function {
static yes test ( void(*)(T*) );
static no test(...);
enum { value = sizeof(yes) == sizeof(test( *(void(*)(T)) 0 ) )} ;
};
------]
I didn't test this extensively though.
The rule I'm using from the Standard is :
8.3.5.3 : [...] The type of a function is determined using the
following rules. The type of each parameter is determined from its own
decl-specifier-seq and declarator. After determining the type of each
parameter, any parameter of type ?array of T? or ?function returning
T? is adjusted to be
?pointer to T? or ?pointer to function returning T,? respectively.
[...]
Very impressive!
Well, the implementation I mentioned and the one you did, both have a
defect:
T can't be reference type, as "pointer to reference is not allowed"
so a specialization of is_function is needed for reference type
template <typename T>
struct is_function<T&> {
enum { value = false };
};
Here is the error message with comeau:
Comeau C/C++ 4.3.10.1 (May 7 2008 20:26:48) for
ONLINE_EVALUATION_BETA1
Copyright 1988-2008 Comeau Computing. All rights reserved.
BD Software STL Message Decryptor (Release 1.24 for Comeau C++)
MODE:strict errors C++ noC++0x_extensions
ComeauTest.c(8): error: array of void is not allowed
template <typename U> static char (&test(U[1]))[2];
^
detected during:
instantiation of "function<void>::test" based on template argument
<void>
at line 10
instantiation of class "function<void>" at line 16
ComeauTest.c(8): error: array of functions is not allowed
template <typename U> static char (&test(U[1]))[2];
^
detected during:
instantiation of "function<void ()>::test" based on template
argument <void
()> at line 10
instantiation of class "function<void ()>" at line 18
2 errors detected in the compilation of "ComeauTest.c".
I have no problem implementing the requirement. What I found strange
here is that SFINAE does not seem to work. Look at the error message,
it's an instantiation error, by definition, SFINAE should kick in and
the ... version should be used. That's what I don't get. I am not
quite sure if 8.3.5.3 is relevant here: array of T decays to pointer
to T. void * or void (*)() would have been ok. Why does not it cause
error with void (*)[1]? It's a pointer to an array of size 1 of void
type. Not fundamentally different from void[1], both are invalid
types.
I quite agree with you.