Detect if class has overloaded function fails on Comeau compiler - c++

I'm trying to use SFINAE to detect if a class has an overloaded member function that takes a certain type. The code I have seems to work correctly in Visual Studio and GCC, but does not compile using the Comeau online compiler.
Here is the code I'm using:
#include <stdio.h>
//Comeau doesnt' have boost, so define our own enable_if_c
template<bool value> struct enable_if_c { typedef void type; };
template<> struct enable_if_c< false > {};
//Class that has the overloaded member function
class TestClass
{
public:
void Func(float value) { printf( "%f\n", value ); }
void Func(int value) { printf( "%i\n", value ); }
};
//Struct to detect if TestClass has an overloaded member function for type T
template<typename T>
struct HasFunc
{
template<typename U, void (TestClass::*)( U )> struct SFINAE {};
template<typename U> static char Test(SFINAE<U, &TestClass::Func>*);
template<typename U> static int Test(...);
static const bool Has = sizeof(Test<T>(0)) == sizeof(char);
};
//Use enable_if_c to only allow the function call if TestClass has a valid overload for T
template<typename T> typename enable_if_c<HasFunc<T>::Has>::type CallFunc(TestClass &test, T value) { test.Func( value ); }
int main()
{
float value1 = 0.0f;
int value2 = 0;
TestClass testClass;
CallFunc( testClass, value1 ); //Should call TestClass::Func( float )
CallFunc( testClass, value2 ); //Should call TestClass::Func( int )
}
The error message is: no instance of function template "CallFunc" matches the argument list. It seems that HasFunc::Has is false for int and float when it should be true.
Is this a bug in the Comeau compiler? Am I doing something that's not standard? And if so, what do I need to do to fix it?
Update
I guess the question now becomes, if this is a bug, is there anything I can do to work around it? I tried using a static_cast on &TestClass::Func, but either that isn't possible or I didn't get the syntax right because I couldn't get it to compile.
If that's not a solution, is there any modifications I can make either to TestClass or HasFunc in order to work around the issue?

I suspect the problem is that as TestClass overloads Func and the Comeau compiler is unable to disambiguate &TestClass::Func, even it it should.

Related

Using SFINAE to detect if overloaded free-standing function exists at compile-time

Here is my unsuccessful attempt at detecting whether a free-standing function void set( T& , void (T::*Func)( const char* ) , const char* str ) exists for any class/struct T, in C++98/03.
#include <iostream>
#include <typeinfo>
struct Foo;
struct Bar;
struct Fuu;
void set( Foo& , void (Foo::*Func)( const char* ) , const char* str )
{
}
void set( Bar& , void (Bar::*Func)( const char* ) , const char* str )
{
}
template <typename T>
class setter_is_implemented
{
public:
typedef void (*SetterFunction)( T& , void (T::*)( const char* ) , const char* );
typedef char one;
typedef long two;
template <typename C> static one test( C c, SetterFunction = c ) ;
template <typename C> static two test(...);
public:
enum { value = sizeof( test<T>(&set)) == sizeof(one) };
};
int main()
{
std::cout << setter_is_implemented<Foo>::value << std::endl;
std::cout << setter_is_implemented<Bar>::value << std::endl;
std::cout << setter_is_implemented<Fuu>::value << std::endl;
}
GCC error message
Test.cpp:24:66: error: ‘c’ was not declared in this scope
template <typename C> static one test( C c, SetterFunction = c ) ;
^
Test.cpp: In instantiation of ‘class setter_is_implemented<Foo>’:
Test.cpp:33:44: required from here
Test.cpp:28:35: error: address of overloaded function with no contextual type information
enum { value = sizeof( test<T>(&set)) == sizeof(one) };
^
Test.cpp: In instantiation of ‘class setter_is_implemented<Bar>’:
Test.cpp:34:44: required from here
Test.cpp:28:35: error: address of overloaded function with no contextual type information
Test.cpp: In instantiation of ‘class setter_is_implemented<Fuu>’:
Test.cpp:35:44: required from here
Test.cpp:28:35: error: address of overloaded function with no contextual type information
AFAIK, taking the address of an overloaded function happens before overload resolution, so SFINAE cannot work in that way. This is also harder because your function returns void (otherwise, one would just check the size of the result ). My C++03 metaprogramming is rusty, but this should work (live on coliru):
namespace setter_is_implemented_detail {
struct dummy1 { char c[2]; };
typedef char dummy2;
dummy2 operator,(dummy1, dummy1);
template<typename T> dummy1 set(T const&,...);
template <typename T>
struct impl
{
typedef void (T::*FT)( const char* );
static T& x;
enum { value = sizeof( set(x,static_cast<FT>(0),static_cast<const char*>(0)), dummy1() ) != sizeof(dummy2) };
};
}
template <typename T>
struct setter_is_implemented: setter_is_implemented_detail::impl<T>{};
note a few things:
set() needs to be found by ADL here (not a big deal, as far as I can tell from your problem description)(*)
the comma operator trick(**) is needed due to the void return type; in gcc, you can take the sizeof(void), so the code can be simplified there
this won't work for non object types (due to the static T&). It can be made to work though, if you need so...
(*) Note that this cannot work for every possible set() overload; this is true for any sfinae, even in c++17, set() must always be sfinae-friendly in order to work.
If you need to match sfinae-friendly set() overloads exactly, it's still possible to do it, but it's more complex; I'd do it in two phases: first you use the above code to find possible candidates, then you check the function pointer conversion, somewhat like you do in your original code ..
(**) This trick works because if set() has void return type (and hence exists) the comma is always interpreted as the built-in comma operator (see c++03[3.9.1/9]: "An expression of type void shall be used only as an expression statement (6.2), as an operand of a comma expression[...]") resulting in the right-most expression. Otherwise, the dummy set and comma operator are used.

Force template method in non-template class

I try to achieve the following behavior/syntax/usage of this class:
Data1 dataType1;
Data2 dataType2;
int intType;
float floatType;
dataType1.method( intType );
dataType1.method( floatType );
dataType2.method( intType );
dataType2.method( floatType );
My approach would be this:
struct CDataBase
{
template< typename T > virtual void method( T type ) = 0;
};
struct CData1 : CDataBase
{
template< typename T > void method( T type ) {}
};
struct CData2 : CDataBase
{
template< typename T > void method( T type ) {}
};
However virtual template methods aren't possible. Also there is no need for an actual base class, However I have to ensure that some classes got a (template) 'method()' implemented.
How do I force a non-templated class/struct to override a template method?
EDIT:
This is my actual layout:
struct Data0
{
int someVar;
template< class T >
void decode( T& type )
{
type.set( someVar );
}
};
EDIT:
in the current version of C++ (11) the behavoir I try to achieve isn't possible. In addition to that, I should really recode this part to avoid this problem. However I accept the only answer given, thanks for you affort.
The basic idea to check for specific functions implemented of a given template parameter type, is to try instantiate function pointers of these. The compiler will complain, if the function pointer initializations cannot be resolved.
Here's some sample code to illustrate the principle:
template<typename T>
void check_has_foo_function() {
void (T::*check)(int, double) = &T::foo;
(void)check;
}
struct A {
void foo(int, double) {};
};
struct B {
void bar(int, double) {};
};
template<typename CheckedClass>
struct Client {
void doSomething() {
check_has_foo_function<CheckedClass>();
CheckedClass x;
x.foo(5,3.1415);
}
};
int main() {
Client<A> clientA;
clientA.doSomething();
// Uncomment the following lines to see the compilation fails
// Client<B> clientB;
// clientB.doSomething();
return 0;
}
Note the call to the check_has_foo_function<CheckedClass>(); function will be completely optimized out, and doesn't have any impact on runtime performance.
Based upon this, further abstractions could be provided (e.g. to generate checks using preprocessor macros). I have published a little experimental framework on GitHub that uses these techniques.

SFINAE to Selectively Include Member

I am trying to write a template class which may or may not define a particular member function depending on its template parameter type. Further the return type of this member function depends on the return type of of a member of the template paramter (if defined).
Below is a minimal example of my code
#include <iostream>
#include <type_traits>
template <typename T>
struct has_foo_int {
private:
template <typename U>
static decltype(std::declval<U>().foo(0), void(), std::true_type()) test(int);
template <typename>
static std::false_type test(...);
public:
typedef decltype(test<T>(0)) test_type;
enum { value = test_type::value };
};
template <typename T, bool HasFooInt>
struct foo_int_return_type;
template<typename T>
struct foo_int_return_type<T,false> {};
template<typename T>
struct foo_int_return_type<T,true> {
using type = decltype(std::declval<T>().foo(0));
};
template<typename T>
struct mystruct
{
T val;
//auto someMethod(int i) -> decltype(std::declval<T>().foo(0)) // error: request for member ‘foo’ in ‘std::declval<double>()’, which is of non-class type ‘double’
//auto someMethod(int i) -> typename foo_int_return_type<T,has_foo_int<T>::value>::type // error: no type named ‘type’ in ‘struct foo_int_return_type<double, false>’
template<typename R=typename foo_int_return_type<T,has_foo_int<T>::value>::type> R someMethod(int i) // error: no type named ‘type’ in ‘struct foo_int_return_type<double, false>’
{
return val.foo(i);
}
};
struct with_foo_int {
int foo(int i){
return i+1;
}
};
using namespace std;
int main(void)
{
mystruct<with_foo_int> ms1;
cout << ms1.someMethod(41) << endl;
mystruct<double> ms2;
return 0;
}
What I would like to happen is that the code compiles fine and outputs 42 for ms1.someFunc(41). I would also expect that if one accidentally tried to call someFunc on ms2 that it would fail to compile.
Unfortunately each of the alternatives I have tried has failed. The first and second, I think I understand why they wouldn't work.
I read here that SFINAE only works for template functions so I tried giving a dummy template parameter to work out the return type but this too fails in the same way.
I'm clearly not understanding something here, what am I missing? Is it possible to achieve what I'm trying to do?
Thanks.
P.s. I'm using g++ 4.7.3
P.p.s I have also tried std::enable_if but get much the same results as with my foo_int_return_type struct.
Here is a short, tidy and documented way of doing what you are attempting,
with some possible bugs addressed thereafter.
#include <type_traits>
/*
Template `has_mf_foo_accepts_int_returns_int<T>`
has a static boolean public member `value` that == true
if and only if `T` is a class type that has a public
member function or member function overload
`int T::foo(ArgType) [const]` where `ArgType`
is a type to which `int` is implicitly convertible.
*/
template <typename T>
struct has_mf_foo_accepts_int_returns_int {
/* SFINAE success:
We know now here `int *` is convertible to
"pointer to return-type of T::foo(0)"
*/
template<typename A>
static constexpr bool test(
decltype(std::declval<A>().foo(0)) *prt) {
/* Yes, but is the return-type of `T::foo(0)`
actually *the same* as `int`?...
*/
return std::is_same<int *,decltype(prt)>::value;
}
// SFINAE failure :(
template <typename A>
static constexpr bool test(...) {
return false;
}
/* SFINAE probe.
Can we convert `(int *)nullptr to
"pointer to the return type of T::foo(0)"?
*/
static const bool value = test<T>(static_cast<int *>(nullptr));
};
template<typename T>
struct mystruct
{
using has_good_foo = has_mf_foo_accepts_int_returns_int<T>;
T val;
/* SFINAE:
`template<typename R> R someMethod(R)` will be this if and only
if `R` == `int` and `has_good_foo` == true.
*/
template<typename R = int>
typename std::enable_if<
(has_good_foo::value && std::is_same<R,int>::value),R
>::type
someMethod(R i) {
return val.foo(i);
}
/* SFINAE:
`template<typename R> R someMethod(R)` will be this if and only
if `R` != `int` or `has_good_foo` != true.
*/
template<typename R = int>
typename std::enable_if<
!(has_good_foo::value && std::is_same<R,int>::value),R
>::type
someMethod(R i) {
static_assert(has_good_foo::value && std::is_same<R,int>::value,
"mystruct<T> does not implement someMethod(R)");
return i;
}
};
// Testing...
#include <iostream>
struct with_foo_int
{
int foo(int i) {
return i + 1;
}
};
using namespace std;
int main(void)
{
mystruct<with_foo_int> ms1;
cout << ms1.someMethod(41) << endl;
mystruct<double> ms2;
cout << ms2.someMethod(41) << endl; // static_assert failure
return 0;
}
This solution faithfully reproduces a couple of possible loopholes in your
own attempt as posted:-
1) It looks as if you may believe that evaluating std::declval<U>().foo(0) is
a SFINAE way of determining whether U::foo exists and takes a single argument
of type int. It doesn't. It is merely a SFINAE way of determining whether
U::foo(ArgType) exists where ArgType is anything to which 0 is
implicitly convertible. Thus ArgType could be any pointer-or-arithmetic
type, not just int.
2) You may not have considered that std::declval<U>().foo(0) will be satisfied
if either or both of U::foo(ArgType) U::foo(ArgType) const exists. You
may well care whether you call a const or a non-const member function on
U, and you would certainly care which of two member function you call. If
with_foo_int were defined as:
struct with_foo_int
{
int foo(int i) const {
return i + 1;
}
int foo(int i) {
return i + 2;
}
};
then the solution given would call the non-const overload and
ms1.someMethod(41) would == 43.
2) Is easily dealt with. If you wish to ensure that you can only call
T::foo(ArgType) const then add a const qualifier to mystruct::someMethod.
If you don't care or wish only to call T::foo(ArgType) then leave things
as they are.
1) is a little harder to solve, because you must craft a SNIFAE probe for
T::foo that is satisfied only if it has the right signature, and that
signature will either be const qualified or not. Let's assume you want
int T::foo(int) const. In that case, replace template
has_mf_foo_accepts_int_returns_int with:
/* Template `has_mf_foo_arg_int_returns_int<T>
has a static boolean public member `value` that == true
if and only if `T` is a class type that has an un-overloaded
a public member `int T::foo(int) const`.
*/
template< typename T>
struct has_mf_foo_arg_int_returns_int
{
/* SFINAE foo-has-correct-sig :) */
template<typename A>
static std::true_type test(int (A::*)(int) const) {
return std::true_type();
}
/* SFINAE foo-exists :) */
template <typename A>
static decltype(test(&A::foo))
test(decltype(&A::foo),void *) {
/* foo exists. What about sig? */
typedef decltype(test(&A::foo)) return_type;
return return_type();
}
/* SFINAE game over :( */
template<typename A>
static std::false_type test(...) {
return std::false_type();
}
/* This will be either `std::true_type` or `std::false_type` */
typedef decltype(test<T>(0,0)) type;
static const bool value = type::value; /* Which is it? */
};
and in template mystruct replace:
using has_good_foo = has_mf_foo_accepts_int_returns_int<T>;
with:
using has_good_foo = has_mf_foo_arg_int_returns_int<T>;
(Template has_mf_foo_arg_int_returns_int is adapted
from my other answer and
you can read how it works there.)
What you gain in SFINAE-precision from the latter approach comes at
a price. The approach requires you to attempt to take the address of T::foo,
to see if it exists. But C++ will not give you the address of an overloaded
member function, so this approach will fail if T::foo is overloaded.
The code here will compile (or appropriately static_assert) with
GCC >= 4.7.2 clang >= 3.2.

How do I avoid implicit conversions on non-constructing functions?

How do I avoid implicit casting on non-constructing functions?
I have a function that takes an integer as a parameter,
but that function will also take characters, bools, and longs.
I believe it does this by implicitly casting them.
How can I avoid this so that the function only accepts parameters of a matching type, and will refuse to compile otherwise?
There is a keyword "explicit" but it does not work on non-constructing functions. :\
what do I do?
The following program compiles, although I'd like it not to:
#include <cstdlib>
//the function signature requires an int
void function(int i);
int main(){
int i{5};
function(i); //<- this is acceptable
char c{'a'};
function(c); //<- I would NOT like this to compile
return EXIT_SUCCESS;
}
void function(int i){return;}
*please be sure to point out any misuse of terminology and assumptions
Define function template which matches all other types:
void function(int); // this will be selected for int only
template <class T>
void function(T) = delete; // C++11
This is because non-template functions with direct matching are always considered first. Then the function template with direct match are considered - so never function<int> will be used. But for anything else, like char, function<char> will be used - and this gives your compilation errrors:
void function(int) {}
template <class T>
void function(T) = delete; // C++11
int main() {
function(1);
function(char(1)); // line 12
}
ERRORS:
prog.cpp: In function 'int main()':
prog.cpp:4:6: error: deleted function 'void function(T) [with T = char]'
prog.cpp:12:20: error: used here
This is C++03 way:
// because this ugly code will give you compilation error for all other types
class DeleteOverload
{
private:
DeleteOverload(void*);
};
template <class T>
void function(T a, DeleteOverload = 0);
void function(int a)
{}
You can't directly, because a char automatically gets promoted to int.
You can resort to a trick though: create a function that takes a char as parameter and don't implement it. It will compile, but you'll get a linker error:
void function(int i)
{
}
void function(char i);
//or, in C++11
void function(char i) = delete;
Calling the function with a char parameter will break the build.
See http://ideone.com/2SRdM
Terminology: non-construcing functions? Do you mean a function that is not a constructor?
8 years later (PRE-C++20, see edit):
The most modern solution, if you don't mind template functions -which you may mind-, is to use a templated function with std::enable_if and std::is_same.
Namely:
// Where we want to only take int
template <class T, std::enable_if_t<std::is_same_v<T,int>,bool> = false>
void func(T x) {
}
EDIT (c++20)
I've recently switched to c++20 and I believe that there is a better way. If your team or you don't use c++20, or are not familiar with the new concepts library, do not use this. This is much nicer and the intended method as outlines in the new c++20 standard, and by the writers of the new feature (read a papers written by Bjarne Stroustrup here.
template <class T>
requires std::same_as(T,int)
void func(T x) {
//...
}
Small Edit (different pattern for concepts)
The following is a much better way, because it explains your reason, to have an explicit int. If you are doing this frequently, and would like a good pattern, I would do the following:
template <class T>
concept explicit_int = std::same_as<T,int>;
template <explicit_int T>
void func(T x) {
}
Small edit 2 (the last I promise)
Also a way to accomplish this possibility:
template <class T>
concept explicit_int = std::same_as<T,int>;
void func(explicit_int auto x) {
}
Here's a general solution that causes an error at compile time if function is called with anything but an int
template <typename T>
struct is_int { static const bool value = false; };
template <>
struct is_int<int> { static const bool value = true; };
template <typename T>
void function(T i) {
static_assert(is_int<T>::value, "argument is not int");
return;
}
int main() {
int i = 5;
char c = 'a';
function(i);
//function(c);
return 0;
}
It works by allowing any type for the argument to function but using is_int as a type-level predicate. The generic implementation of is_int has a false value but the explicit specialization for the int type has value true so that the static assert guarantees that the argument has exactly type int otherwise there is a compile error.
Maybe you can use a struct to make the second function private:
#include <cstdlib>
struct NoCast {
static void function(int i);
private:
static void function(char c);
};
int main(){
int i(5);
NoCast::function(i); //<- this is acceptable
char c('a');
NoCast::function(c); //<- Error
return EXIT_SUCCESS;
}
void NoCast::function(int i){return;}
This won't compile:
prog.cpp: In function ‘int main()’:
prog.cpp:7: error: ‘static void NoCast::function(char)’ is private
prog.cpp:16: error: within this context
For C++14 (and I believe C++11), you can disable copy constructors by overloading rvalue-references as well:
Example:
Say you have a base Binding<C> class, where C is either the base Constraint class, or an inherited class. Say you are storing Binding<C> by value in a vector, and you pass a reference to the binding and you wish to ensure that you do not cause an implicit copy.
You may do so by deleting func(Binding<C>&& x) (per PiotrNycz's example) for rvalue-reference specific cases.
Snippet:
template<typename T>
void overload_info(const T& x) {
cout << "overload: " << "const " << name_trait<T>::name() << "&" << endl;
}
template<typename T>
void overload_info(T&& x) {
cout << "overload: " << name_trait<T>::name() << "&&" << endl;
}
template<typename T>
void disable_implicit_copy(T&& x) = delete;
template<typename T>
void disable_implicit_copy(const T& x) {
cout << "[valid] ";
overload_info<T>(x);
}
...
int main() {
Constraint c;
LinearConstraint lc(1);
Binding<Constraint> bc(&c, {});
Binding<LinearConstraint> blc(&lc, {});
CALL(overload_info<Binding<Constraint>>(bc));
CALL(overload_info<Binding<LinearConstraint>>(blc));
CALL(overload_info<Binding<Constraint>>(blc));
CALL(disable_implicit_copy<Binding<Constraint>>(bc));
// // Causes desired error
// CALL(disable_implicit_copy<Binding<Constraint>>(blc));
}
Output:
>>> overload_info(bc)
overload: T&&
>>> overload_info<Binding<Constraint>>(bc)
overload: const Binding<Constraint>&
>>> overload_info<Binding<LinearConstraint>>(blc)
overload: const Binding<LinearConstraint>&
>>> overload_info<Binding<Constraint>>(blc)
implicit copy: Binding<LinearConstraint> -> Binding<Constraint>
overload: Binding<Constraint>&&
>>> disable_implicit_copy<Binding<Constraint>>(bc)
[valid] overload: const Binding<Constraint>&
Error (with clang-3.9 in bazel, when offending line is uncommented):
cpp_quick/prevent_implicit_conversion.cc:116:8: error: call to deleted function 'disable_implicit_copy'
CALL(disable_implicit_copy<Binding<Constraint>>(blc));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Full Source Code: prevent_implicit_conversion.cc
Well, I was going to answer this with the code below, but even though it works with Visual C++, in the sense of producing the desired compilation error, MinGW g++ 4.7.1 accepts it, and invokes the rvalue reference constructor!
I think it must be a compiler bug, but I could be wrong, so – anyone?
Anyway, here's the code, which may turn out to be a standard-compliant solution (or, it may turn out that that's a thinko on my part!):
#include <iostream>
#include <utility> // std::is_same, std::enable_if
using namespace std;
template< class Type >
struct Boxed
{
Type value;
template< class Arg >
Boxed(
Arg const& v,
typename enable_if< is_same< Type, Arg >::value, Arg >::type* = 0
)
: value( v )
{
wcout << "Generic!" << endl;
}
Boxed( Type&& v ): value( move( v ) )
{
wcout << "Rvalue!" << endl;
}
};
void function( Boxed< int > v ) {}
int main()
{
int i = 5;
function( i ); //<- this is acceptable
char c = 'a';
function( c ); //<- I would NOT like this to compile
}
I first tried PiotrNycz's approach (for C++03, which I'm forced to use for a project), then I tried to find a more general approach and came up with this ForcedType<T> template class.
template <typename T>
struct ForcedType {
ForcedType(T v): m_v(v) {}
operator T&() { return m_v; }
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(T2);
T m_v;
};
template <typename T>
struct ForcedType<const T&> {
ForcedType(const T& v): m_v(v) {}
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(const T2&);
const T& m_v;
};
template <typename T>
struct ForcedType<T&> {
ForcedType(T& v): m_v(v) {}
operator T&() { return m_v; }
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(T2&);
T& m_v;
};
If I'm not mistaken, those three specializations should cover all common use cases. I'm not sure if a specialization for rvalue-reference (on C++11 onwards) is actually needed or the by-value one suffices.
One would use it like this, in case of a function with 3 parameters whose 3rd parameter doesn't allow implicit conversions:
function(ParamType1 param1, ParamType2 param2, ForcedType<ParamType3> param3);

Why is term not evaluating to a function taking 0 arguments?

When I try compiling
template<bool val>
struct boolean { static const bool value = val; };
template<typename T>
struct is_callable : boolean<sizeof((*(T*)0)()) >= 0> { }; // error!
int main(void) { bool b = is_callable<int (*)()>::value; }
I get:
error C2064: term does not evaluate to a function taking 0 arguments
see reference to class template instantiation 'is_callable<T>' being compiled
I'm pretty sure int (*)() is callable with 0 arguments... so why doesn't this compile?
The problem is not the use of int(). You can completely remove that from the example and get the same error. The problem is the sizeof expression itself when used as a non-type template argument. Example
template<bool val>
struct boolean { };
template<typename T>
struct is_callable : boolean<sizeof((*(T*)0)()) >= 0> // Error
{
void Test()
{
auto x = sizeof((*(T*)0)()) >= 0; // Compiles
}
};
Hopefully another C++ guy can come along and determine if this sizeof expression is simply illegal as a type argument or if this is just a limitation in the MS C++ compiler.
For me this works.
typedef int (*X)();
template<typename T>
struct is_callable : boolean<sizeof((*(X*)(T*)0)()) >= 0> { }; // works!
So, it looks like the compiler is not sure that you will always pass a function pointer to T when you instantiate the template class !. So, force the compiler with an explicit cast.
[Edit] : Also, on further thinking, I don't understand what you are really trying to do. Are you trying to measure the size of a function pointer which takes a single parameter? How this is going to be different for functions with different return types? Why do you need template at all for a constant expression (which is sizeof(void*))?
Please check this thread for more understanding
What is guaranteed about the size of a function pointer?
You could just use simple template specialization.
#include <stdio.h>
template<typename T>
struct func_with_zero_args { static const bool value = false; };
template<>
struct func_with_zero_args <int (*)()> { static const bool value = true; };
#define STRINGIFY(t) "" #t
#define TEST(t) printf(STRINGIFY(t) ": %s\n", (func_with_zero_args<t>::value ? "yes" : "no"));
int
main(int argc, const char* argv[])
{
TEST(void);
TEST(void (*)(void));
TEST(void (*)(int));
TEST(int (*)(void));
TEST(int (*)(int));
return 0;
}
Generates (using g++ (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3)
void: no
void (*)(void): no
void (*)(int): no
int (*)(void): yes
int (*)(int): no