Why doesn't the term evaluate a function that takes 0 arguments?

When I try to compile

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 sure int (*)() can be called with arguments 0 ... so why doesn't this compile?

+4
source share
3 answers

The problem is not using int() . You can completely remove this from the example and get the same error. The problem lies in the sizeof expression itself when using a non-type type template as an 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 guy from C ++ can come and determine if this sizeof expression is simply illegal as a type argument or is it just a restriction in the MS C ++ compiler.

0
source

It works for me.

  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 pointer to the T function when instantiating the template class !. So, forcibly create an explicit cast compiler.

[Edit]: Also, thinking, I don’t understand what you are really trying to do. Are you trying to measure the size of a function pointer that takes one parameter? How will this differ for functions with different return types? Why do we need a template in general for a constant expression (sizeof (void *))?

Please browse through this topic to find out more. What is guaranteed regarding the size of a function pointer?

0
source

You can simply use the special 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; } 

Creates (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
0
source

Source: https://habr.com/ru/post/1389577/


All Articles