Is it possible to check if a function has a void return type

This very strange request came ...

I need to do a compile-time check if the current function has a return type of void or not, and compilation fails if the return type is void .

I tried to do the magic with http://en.cppreference.com/w/cpp/types/result_of and decltype , but I just can't get any closer to the solution.

 #include <type_traits> void other_func(void) { } void test_maxi(void) { typedef decltype(&::other_func) TYPE; static_assert(std::is_same<TYPE, void>::value, "not void"); } int main() { } 

So the question is:

Is it possible to do this for the current function ?

EDIT The return type check must be performed in the macro, as it will be used in several functions.

+7
c ++ c ++ 11
source share
5 answers

You can implement compile-time checking if one string literal starts from another, and use the __PRETTY_FUNCTION__ macro, which is set to a string literal that starts with the type of the returned function. You should check if this macro starts with void followed by a space.

This code compiles fine:

 constexpr bool startsWith(const char* a, const char* b) { return *a == *b && (*(a + 1) == '\0' || startsWith(a + 1, b + 1)); } int f() { static_assert(!startsWith("void ", __PRETTY_FUNCTION__), "not void"); return 1; } int main() { } 

If you change f return type to void :

 constexpr bool startsWith(const char* a, const char* b) { return *a == *b && (*(a + 1) == '\0' || startsWith(a + 1, b + 1)); } void f() { static_assert(!startsWith("void ", __PRETTY_FUNCTION__), "not void"); } int main() { } 

static_assert will fire.

The __PRETTY_FUNCTION__ macro seems specific to the GNU C ++ compiler, however, clang++ works just fine, as it also defines this macro. If you use a different compiler, you should check if this macro is installed, and if not, read the compiler documentation to determine similar macros, for example, __FUNCSIG__ .

You can play with #ifdef __PRETTY_FUNCTION__ ... to make it more portable between different compilers, but I think this is a topic for another question.

+13
source share

If you can name the current function, the easiest way is:

 static_assert(!std::is_same<decltype(test_maxi()), void>::value, "void"); 
+4
source share

You can check the return type of the current function by checking if the dead return compile:

 struct ConvertToAnything { template <class T> operator T() const { assert(!"Don't call me!"); } }; #define CHECK_NONVOID_RETURN() if(true); else return ConvertToAnything{} int f() { CHECK_NONVOID_RETURN(); // Passes return 42; } void g() { CHECK_NONVOID_RETURN(); // Fails at compile-time } 

The void case is special, so that's enough. But you can also prohibit other types by overloading ConvertToAnything::operator Type() = delete; . Allow void bit more proactive, but still possible.

+3
source share

Try the following:

 template <typename ... Args> constexpr bool return_void(void(Args ...)) { return true; } template <typename R, typename ... Args> constexpr bool return_void(R(Args ...)) { return false; } 

Suppose we have the following functions:

 void f() {} void g(int) {} void h(int*,char&) {} void i(float,bool) {} void j(const char *const) {} void k(void()) {} int l() { return {}; } float m(int) { return {}; } 

All calls to return_void will return true, while it is called with the first six functions, calling return_void(l) and return_void(m) returns false because they will call the second version of the template, returns false.

Check it out online

This will let you check if the void function is returned at runtime and compile time:

 int main() { static_assert(return_void(f), "not void"); if (!return_void(m)) std::cout << "m result is: " << m(0) << '\n'; return 0; } 
+1
source share

All you need to do is determine the type of return value and check if it is a void type. To check the type, you can use std::is_void . return type can be detected using the following pattern:

 #include <type_traits> // for is_void template<typename R, typename... A> void test(R (*func)(A...)) { static_assert( !std::is_void<R>::value, "void return type is not allowed" ); } // functions to check: void a(int, char*) {} int b(char, float) {return 0;} int main() { test(a); // < assert triggered here test(b); } 
0
source share

All Articles