这个非常奇怪的要求出现了......
我需要进行编译时检查当前函数是否具有void
返回类型,如果返回类型为void
则无法编译。
我也尝试用http://en.cppreference.com/w/cpp/types/result_of和decltype
做一些魔术,但是我无法接近解决方案。
#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() {
}
所以问题出现了:
是否可以为当前功能执行此操作?
编辑返回类型检查应该放在宏中,因为它将在多个函数中使用。
答案 0 :(得分:14)
如果一个字符串文字以另一个字符串开头,则可以实现编译时检查,并使用__PRETTY_FUNCTION__
宏,该宏设置为以函数返回类型开头的字符串文字。您应该检查此宏是否以void
开头,后跟空格。
此代码编译良好:
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() {
}
如果您将f
返回类型更改为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
会开火。
__PRETTY_FUNCTION__
宏似乎特定于GNU C ++编译器,但clang++
工作正常,因为它也定义了这个宏。如果您正在使用其他编译器,则应检查此宏是否确实已设置,如果没有,请阅读编译器文档以确定类似
宏,例如__FUNCSIG__
。
你可以使用#ifdef __PRETTY_FUNCTION__ ...
来使各种编译器之间更容易移植,但我相信这是另一个问题的主题。
答案 1 :(得分:4)
如果您可以命名当前功能,那么最简单的方法是:
static_assert(!std::is_same<decltype(test_maxi()), void>::value, "void");
答案 2 :(得分:4)
试试这个:
tablediff <your parameters> | findstr /i "^Mismatch ^Src"
我们假设我们有以下功能:
template <typename ... Args>
constexpr bool return_void(void(Args ...)) { return true; }
template <typename R, typename ... Args>
constexpr bool return_void(R(Args ...)) { return false; }
对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 {}; }
的所有调用都将返回true,只要使用前六个函数调用它,return_void
和return_void(l)
调用将返回false,因为它们将调用第二个版本模板,返回假的。
这将允许您在运行时和编译时检查函数是否返回return_void(m)
:
void
答案 3 :(得分:3)
您可以通过检查死return
是否可以编译来检查当前函数的返回类型:
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
}
void
的情况属于特殊情况,所以这就足够了。但您也可以通过重载ConvertToAnything::operator Type() = delete;
禁止其他类型。允许void
涉及更多,但仍然可行。
答案 4 :(得分:0)
您需要的只是检测返回类型并检查它是否为void类型。要检查类型,您可以使用std::is_void
。可以使用以下模板检测返回类型:
#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);
}