473,848 Members | 1,760 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

type function U[1] and U(*)[1] SFINAE issue

Hello, I just hit a strange problem regarding SFINAE. The following code
causes compile error (void cannot be array element type), I thought
SFINA should match test(...) version instead and not issue any error.

If I replace U[1] with U(*)[1], then the code compiles again. I couldn't
make the sense out of it. What's the magic with (*)? Note that
function<int>:: yes returns correct result 0 even with U[1].

Please help me out.

Fei

#include <iostream>
using namespace std;

template <typename T>
struct function{

template <typename Ustatic char test(...);
template <typename Ustatic char (&test(U[1]))[2];

enum { yes = (sizeof(functio n<T>::test<T>(0 )) == 1) };
};

int main(){

cout << "int: " << function<int>:: yes << endl;
cout << "void: " << function<void>: :yes << endl;
// function
cout << "void(): " << function<void() >::yes << endl;
// function ptr
cout << "void(*)(): " << function<void(* )()>::yes << endl;
}
Jun 27 '08 #1
5 2082
On May 24, 5:10*am, Fei Liu <fei....@gmail. comwrote:
Hello, I just hit a strange problem regarding SFINAE. The following code
causes compile error (void cannot be array element type), I thought
SFINA should match test(...) version instead and not issue any error.

If I replace U[1] with U(*)[1], then the code compiles again. I couldn't
make the sense out of it. What's the magic with (*)? Note that
function<int>:: yes returns correct result 0 even with U[1].

What compiler are you using?

as long as U is a function type, U[1] is illformed, array of function
is not allowed.

when you say "U[1]" as a function parameter type, it's deprecated as
"U*"
when you say "U(*)[1]", it's a pointer to array of U.
>
Please help me out.

Fei

#include <iostream>
using namespace std;

template <typename T>
struct function{

* * *template <typename Ustatic char test(...);
* * *template <typename Ustatic char (&test(U[1]))[2];

* * *enum { yes = (sizeof(functio n<T>::test<T>(0 )) == 1) };

};
could you explain your algorithm here?
>
int main(){

* * *cout << "int: " << * * * * * * *function<int>: :yes << endl;
* * *cout << "void: " << * * * * * * function<void>: :yes<< endl;
* * *// function
* * *cout << "void(): " << * * * * * function<void() >::yes<< endl;
* * *// function ptr
* * *cout << "void(*)(): " << * * * *function<void( *)()>::yes << endl;

}

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));
};
__
Best Regards
Barry
Jun 27 '08 #2
On 24 mai, 04:16, Barry <dhb2...@gmail. comwrote:
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.
[...]
Alexandre Courpron.
Jun 27 '08 #3
On May 24, 10:28*pm, courp...@gmail. com wrote:
On 24 mai, 04:16, Barry <dhb2...@gmail. comwrote:
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 };
};

Jun 27 '08 #4
On May 25, 10:44 am, Barry <dhb2...@gmail. comwrote:
On May 24, 10:28 pm, courp...@gmail. com wrote:
On 24 mai, 04:16, Barry <dhb2...@gmail. comwrote:
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_EVALUATI ON_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_extensi ons

ComeauTest.c(8) : error: array of void is not allowed
template <typename Ustatic 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 Ustatic char (&test(U[1]))[2];
^
detected during:
instantiation of "function<v oid ()>::test" based on template
argument <void
()at line 10
instantiation of class "function<v oid ()>" 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.

Fei
Jun 27 '08 #5
Fei Liu wrote:
On May 25, 10:44 am, Barry <dhb2...@gmail. comwrote:
>On May 24, 10:28 pm, courp...@gmail. com wrote:
>>On 24 mai, 04:16, Barry <dhb2...@gmail. comwrote:
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_EVALUATI ON_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_extensi ons

ComeauTest.c(8) : error: array of void is not allowed
template <typename Ustatic 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 Ustatic char (&test(U[1]))[2];
^
detected during:
instantiation of "function<v oid ()>::test" based on template
argument <void
()at line 10
instantiation of class "function<v oid ()>" 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.
As the principle of SFINAE is to avoid producing invalid type, I
couldn't find why it doesn't work here
--
Best Regards
Barry
Jun 27 '08 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
2702
by: Peter Collingbourne | last post by:
Hello I am trying to do some template metaprogramming involving enabling or disabling a method in a parameterised class based on some condition. I am trying to use the Boost enable_if mechanism to do this, using the SFINAE principle. Here is a simple example showing what I am trying to do: 1 #include <iostream.h> 2 #include <boost/utility/enable_if.hpp> 3
1
1831
by: Dilip | last post by:
I am a little confused about the difference between SFINAE and unambiguous overload resolution set. For ex: template<typename Tvoid func(T); template<typename Tvoid func(T*); now, func<intis going to be ambiguous. Ok so far so good. Now:
5
2369
by: chrisstankevitz | last post by:
Hi, Q1: Is there a way to make a template function that works only for specific types which produces a compiler error if used with an invalid type? Q2: If not, how do people deal with this issue? I believe A1 is no. I tried below with template function "f". For A2, functors work but have ugly syntax and runtime overhead. A
1
2299
by: siddhu | last post by:
Dear Experts, I am trying to implement "Is a class type" for template arguments using SFINAE. program is like this: #include<iostream> using namespace std; template <typename T>
1
1607
by: Marcin Kalicinski | last post by:
Is there a way, using template metaprogramming techinques like e.g. SFINAE, to determine at compile time if a type supports certain operation (for example if operator == is defined for that type)? // Function for types supporting == template<class Tbool func(T t) { if (t == 3) return true; else
4
1576
by: Gianni Mariani | last post by:
Below is an attempt to factorize the "SFINAE" idiom. I have tried it on three compilers and they all complain. As far as I can tell, it's valid code. The questions are, are the compilers right to reject the code or is the code right and why ? and has anyone successfully mastered the act of factorizing SFINAE? ---------------------------------------------------------------------- template <template <typenameclass w_Test, typename...
2
2478
by: Barry | last post by:
The problem brought by one earlier post from comp.lang.c++ http://groups.google.com/group/comp.lang.c++/browse_thread/thread/bf636c48b84957b/ I take part of the question and reproduce the code to represent (partly) the question. #include <iostream> template <class> void f(...)
3
2458
by: .rhavin grobert | last post by:
guess you have the following: _________________________________________________ template <class T> class CQVector { public: // find an element, returns index or -1 if none is found int find(int id) const; private:
35
2015
by: James Kanze | last post by:
Just ran into an interesting question concerning SFINAE. Given the following code: #include <iostream> #include <typeinfo> template< typename T > class P { public:
0
9738
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
11005
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10349
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9501
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
7070
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5735
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
4544
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4139
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3177
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.