C++ 是否可以检查函数是否具有无效返回类型
这个非常奇怪的请求出现了 我需要在编译时检查当前函数是否有C++ 是否可以检查函数是否具有无效返回类型,c++,c++11,C++,C++11,这个非常奇怪的请求出现了 我需要在编译时检查当前函数是否有void返回类型,如果返回类型为void,则编译失败 我也试着用anddecltype做一些魔术,但是我就是无法接近解决方案 #include <type_traits> void other_func(void) { } void test_maxi(void) { typedef decltype(&::other_func) TYPE; static_assert(std::is_same&l
void
返回类型,如果返回类型为void
,则编译失败
我也试着用anddecltype
做一些魔术,但是我就是无法接近解决方案
#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() {
}
#包括
无效其他函数(无效){}
最大无效测试(无效)
{
typedef decltype(&::other_func)类型;
静态断言(std::is_same::value,“notvoid”);
}
int main(){
}
所以问题来了:
是否可以对当前功能执行此操作
编辑返回类型检查应在宏中进行,因为它将在多个函数中使用。如果可以命名当前函数,最简单的方法是:
static_assert(!std::is_same<decltype(test_maxi()), void>::value, "void");
static_assert(!std::is_same::value,“void”);
如果一个字符串文字以另一个字符串文字开头,则可以实现编译时检查,并使用\uuu PRETTY\u FUNCTION\uuuu
宏,该宏设置为以函数返回类型开头的字符串文字。您应该检查此宏是否以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\u assert
将启动
>代码> Pr.TythyFix.Eng/<代码>宏似乎是特定于GNU C++编译器,但是,<代码> CLAN++//> >工作很好,因为它也定义了这个宏。如果您正在使用另一个编译器,您应该检查是否真的设置了此宏,如果没有,请阅读编译器文档以确定类似的设置 宏,例如,
\uuuu FUNCSIG\uuu
您可以使用
\ifdef\uu PRETTY\u FUNCTION\uuuu…
使其在各种编译器之间更易于移植,但我相信这是另一个问题的主题。您只需检测返回类型并检查它是否为void类型。要检查类型,可以使用std::is\u 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);
}
\include//for is\u void
模板
无效试验(R(*func)(A…){
静态断言(
!std::is_void::value,
“不允许使用无效返回类型”
);
}
//要检查的功能:
void a(int,char*){}
int b(字符,浮点){返回0;}
int main()
{
测试(a);//
您可以通过检查死返回是否可以编译来检查当前函数的返回类型:
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
}
struct ConvertToAnything{
模板
运算符T()常量{assert(!“不要叫我!”);}
};
#定义CHECK_nonoid_RETURN()如果为(true);否则返回ConvertToAnything{}
int f(){
检查_nonoid_RETURN();//通过
返回42;
}
void g(){
CHECK_nonoid_RETURN();//在编译时失败
}
void
的情况是一个特殊的情况,因此这就足够了。但也可以通过重载ConvertToAnything::operator Type()=delete来禁止其他类型代码>。允许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; }
只要使用前六个函数调用,return\u void
的所有调用都将返回true,return\u void(l)
和return\u 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;
}
intmain(){
静态断言(返回无效(f),“非无效”);
如果(!return_void(m))
std::cout Why?如果您试图将void赋值给任何对象,编译器都会对您大喊大叫。没有像当前函数这样的对象,那么如何获取类型?可能使用lambda而不是传统函数?让它作为另一个函数的模板参数的默认值并调用该函数?我想您会遇到与我知道(参见本例)这是一个小问题……我无法命名当前函数,这应该是一种宏类型的构造。@fritzone如果您可以将函数标记为constexpr
,这将起作用。基于将其设为宏的奇怪要求(恶心)这是正确的答案。侧方注释:对于VisualC++,可以使用<代码>·y'SuffsiGuix。非常好。让我补充说,应该检查它是否以“空格”开头,以避免在返回代码< >空*>代码>或自定义结构>代码> VoIDFoO 的情况下开火。<代码>命名空间{Valuy(){\n#ifdef#u PRETTY#u FUNC#n#define BOB 1#else#define BOB 2#endif}
应该得到区分PRETTY FUNC或funcsig的BOB
标记。通过一些游戏,应该能够定义一个\u PRETTY#FUNC#u FUNC#的标记,如果它有效。。。
int main() {
static_assert(return_void(f), "not void");
if (!return_void(m))
std::cout << "m result is: " << m(0) << '\n';
return 0;
}