繁体   English   中英

在 C++ 中获取当前 function 的返回类型

[英]Get return type of current function in C++

这个问题类似于Get return type of function in macro (C++)但它已有 10 年历史,没有得到回答。 任何其他解决方案都将被接受。

我想创建一个断言宏,如果不满足条件,它只从 function 返回,例如:

#define ASSERT(X) if(!(X)) return {};

如果包含 function 返回 void,这将不起作用,但我不想创建 2 个宏。 我希望能够在不更改代码的情况下添加/删除返回值。 我的想法是创建一个助手 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 {};
    }
}

现在宏可以像这样工作:

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;
}

但是我需要当前 function 的返回类型 T 而不必调用诸如ASSERT(i,= nullptr, double)之类的东西,因为这样我就可以简单地使用 2 个宏。 此外,像 __func__ 和 std::source_location 这样的宏只是字符串。

语句return X; X 对于返回 function 的void和返回任意类型的 function 均有效。

可以创建一种特殊的用户定义模板类型,其中return X; 将适用于多种类型。 例如return std::nullopt; 对于返回任何optional<T>的 function 始终有效。 您可以从 object (如nullopt )创建具有类似隐式转换属性的类似类型,该类型具有允许“携带” void类型的特化( std::optional<void>是不允许的,尽管您可以使用无状态类型作为void的等价物)。

当然,这现在需要调用者从您的类型中提取返回值(如果有的话)。 这也意味着它必须检查是否返回了值。

expected<T, E>类型(其中有几种实现)表示您正在谈论的类型。 不同之处在于它们带有TET == void的特殊情况),其中带有E表示期望返回的消费者处理的错误值。

但所有这些都需要更改函数的实际返回值。 如果您对使用简单类型(如voiddoubleint等)很执着,那么无论您正在做什么返回,您都必须使用不同的宏。

这可以使用__PRETTY_FUNCTION__ (GCC, Clang) / __FUNCSIG__ (MSVC) 来实现,这是一个非标准扩展,它为您提供当前 function 的名称,包括返回类型。

您可以在编译时分析字符串以查看它是否包含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);
}

这需要更多的测试,以确保您不能用尾随返回类型破坏它,并通过向 function 定义(属性、调用约定等)添加各种内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM