是否可以检查函数是否具有 void 返回类型
Is it possible to check if the function has a void return type
这个非常奇怪的请求出现了......
我需要做一个编译时检查当前函数是否具有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() {
}
那么问题来了:
是否可以为当前函数执行此操作?
编辑 返回类型检查应该放在宏中,因为它将在多个函数中使用。
一个字符串文本以另一个字符串文本开头,则可以实现编译时检查,并使用__PRETTY_FUNCTION__
宏,该宏设置为以函数返回类型开头的字符串文本。您应该检查此宏是否以void
开头,后跟空格。
这段代码编译得很好:
constexpr bool startsWith(const char* a, const char* b) {
return *a == *b && (*(a + 1) == ' ' || startsWith(a + 1, b + 1));
}
int f() {
static_assert(!startsWith("void ", __PRETTY_FUNCTION__), "not void");
return 1;
}
int main() {
}
如果将返回类型更改为void
f
:
constexpr bool startsWith(const char* a, const char* b) {
return *a == *b && (*(a + 1) == ' ' || 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__ ...
使其在各种编译器之间更具可移植性,但我相信这是另一个问题的主题。
如果你可以命名当前函数,那么最简单的方法是:
static_assert(!std::is_same<decltype(test_maxi()), void>::value, "void");
试试这个:
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 {}; }
只要使用前六个函数调用return_void
,所有对 的调用都将返回 true,return_void(l)
和 return_void(m)
调用将返回 false,因为它们将调用模板的第二个版本,即返回 false 的版本。
在线查看
这将允许您检查函数是否在运行时和编译时返回void
:
int main() {
static_assert(return_void(f), "not void");
if (!return_void(m))
std::cout << "m result is: " << m(0) << 'n';
return 0;
}
可以通过检查死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
有点复杂,但仍然可行。
您所需要的只是检测返回类型并检查它是否为 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);
}
- 在运行时检查继承是否只有一种类型和 void*
- 模板签名解析为 void(void) 被 GCC 拒绝;这是否有效C++?
- 逐字节删除 void* 是否安全?
- 是否可以将已经初始化的变量转换为 void*?
- 通过引用传递参数;函数返回类型是否必须为 VOID?
- 是否可以为 void* 创建shared_ptr?
- 是否强制转换void**并将第一个字节设置为nullptr
- c ++ 我是否需要手动删除指向另一个具体类型的 void* 指针?
- 对 C++ 中的特定标头使用 extern C 关键字是否允许从 void* 转换为 char*?
- 将 void (*p)(SomeType*) 转换为 void (*p)(void*) 是否安全?
- 检查 void* 是否成功使用 static_cast 反对
- 是否有理由大多数/所有 try-catch 示例只对 throw 语句使用 void 子函数
- 是否可以将所有权从void*转移到unique_ptr
- C/C++:是否可以将 Eclipse 项目设置配置为接受 void 指针而不对所有 Linux 发行版进行强制转换
- c++ 检查 Unix 中是否存在目录,如果存在,则调用 void 函数
- 将新放置到缓冲区后,缓冲区和实例是否具有相同的 void* 地址?
- 在一个不带参数的函数的声明中指定void是否解决了Most Vexing Parse
- 是否将invoke_result与void参数类型一起使用
- 如何验证 LLVM "ret"指令是否返回 void?
- Constexpr类模板成员函数是否具有推导的void返回类型