[英]Get return type of current function in C++
This question is similar to Get return type of function in macro (C++) but it is 10 Years old and is not answered.这个问题类似于Get return type of function in macro (C++)但它已有 10 年历史,没有得到回答。 Any other solution would be accepted.任何其他解决方案都将被接受。
I want to create an assert macro that only returns from the function if the condition isn't met, Like:我想创建一个断言宏,如果不满足条件,它只从 function 返回,例如:
#define ASSERT(X) if(!(X)) return {};
This doesn't work if the containing function returns void, but I don't want to create 2 macros.如果包含 function 返回 void,这将不起作用,但我不想创建 2 个宏。 I want to be able to add/remove return values without changing the code.我希望能够在不更改代码的情况下添加/删除返回值。 My idea is to create a helper function:我的想法是创建一个助手 function:
template<class T>
T re(){
if constexpr( std::is_same<T, void>::value ){
return;
}
else if constexpr( ! std::is_same<T, void>::value ){
return {};
}
}
Now the macro could work like:现在宏可以像这样工作:
double f(int *i){
if(i == nullptr){
typedef std::invoke_result<decltype(&f),int>::type T; // only works for this function
return re<T>();
}
return 1.0;
}
But I require the return type T of the current function without having to call something like ASSERT(i,= nullptr, double)
because then I could simply use 2 macros.但是我需要当前 function 的返回类型 T 而不必调用诸如ASSERT(i,= nullptr, double)
之类的东西,因为这样我就可以简单地使用 2 个宏。 Also, macros like __func__ and std::source_location are only strings.此外,像 __func__ 和 std::source_location 这样的宏只是字符串。
There is no expression X
where the statement return X;
语句return X;
X
will be valid for both a void
returning function and a function that returns an arbitrary type.对于返回 function 的void
和返回任意类型的 function 均有效。
One can create a special user-defined template type where return X;
可以创建一种特殊的用户定义模板类型,其中return X;
will be valid for a variety of types.将适用于多种类型。 For example return std::nullopt;
例如return std::nullopt;
is always valid for a function returning any optional<T>
.对于返回任何optional<T>
的 function 始终有效。 You can create a similar type with similar implicit conversion properties from an object like nullopt
, one with a specialization to allow a void
type to be "carried" ( std::optional<void>
is not allowed, though you could use a stateless type as an equivalent to void
).您可以从 object (如nullopt
)创建具有类似隐式转换属性的类似类型,该类型具有允许“携带” void
类型的特化( std::optional<void>
是不允许的,尽管您可以使用无状态类型作为void
的等价物)。
Of course, this now requires the caller to extract the returned value (if any) from your type.当然,这现在需要调用者从您的类型中提取返回值(如果有的话)。 This also means that it has to check to see if a value was returned or not.这也意味着它必须检查是否返回了值。
The expected<T, E>
type (of which there are several implementations) represents a type like what you're talking about. expected<T, E>
类型(其中有几种实现)表示您正在谈论的类型。 The difference is that they carry either a T
or E
(with a special case for T
== void
), where carrying an E
represents an error value that the consumer of the return is expected to handle.不同之处在于它们带有T
或E
( T
== void
的特殊情况),其中带有E
表示期望返回的消费者处理的错误值。
But all these require changing the function's actual return value.但所有这些都需要更改函数的实际返回值。 If you're dead-set on using simple types like void
, double
, int
, etc, then you're going to have to have different macros for whatever return you're doing.如果您对使用简单类型(如void
、 double
、 int
等)很执着,那么无论您正在做什么返回,您都必须使用不同的宏。
This is possible using __PRETTY_FUNCTION__
(GCC, Clang) / __FUNCSIG__
(MSVC), a non-standard extension that gives you the name of the current function, including the return type.这可以使用__PRETTY_FUNCTION__
(GCC, Clang) / __FUNCSIG__
(MSVC) 来实现,这是一个非标准扩展,它为您提供当前 function 的名称,包括返回类型。
You can analyze the string at compile-time to see if it has void
in it or not:您可以在编译时分析字符串以查看它是否包含void
:
#include <string_view>
struct AnyType
{
template <typename T>
operator T()
{
return {};
}
};
template <bool IsVoid>
auto foo()
{
if constexpr (IsVoid)
return;
else
return AnyType{};
}
#ifndef _MSC_VER
#define FUNCNAME __PRETTY_FUNCTION__
#else
#define FUNCNAME __FUNCSIG__
#endif
#define ASSERT(x) if (!bool(x)) return foo<std::string_view(FUNCNAME).starts_with("void ")>()
void x()
{
ASSERT(0);
}
int y()
{
ASSERT(0);
}
This needs more testing to make sure you can't break it with trailing return types, and by adding various stuff to function definition (attributes, calling conventions, etc).这需要更多的测试,以确保您不能用尾随返回类型破坏它,并通过向 function 定义(属性、调用约定等)添加各种内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.