简体   繁体   English

函数的多重返回类型-C ++

[英]Multiple return type from function - C++

Is there any way (conventional or no) to get a choice between multiple specified return types from a function. 是否有任何方法(传统方法或否方法)可从函数中在多个指定的返回类型之间进行选择。 For example: 例如:

/* Concept code... */
class var {
    public:
        union {
            bool _bool;
            int _int;
            char* _char_pointer;
        } primitive_value;
        std::string type;

        var(bool arg) { primitive_value._bool = arg; type = "bool"; }
        var(int arg) { primitive_value._int = arg; type = "int"; }
        var(char* arg) { primitive_value._char_pointer = arg; type = "char*"; }

        // Function/ method that could return `bool`, `int` or `char*`
        <bool, int, char*> valueOf() const {
            if (type == "bool") return primitive_value._bool;
            else if (type == "int") return primitive_value._int;
            else if (type == "char*") return primitive_value._char_pointer;
        }
};

There is a reference to a similar question here I've seen that suggested using void* pointers or union 's but I have yet to fully understand how those work. 我在这里看到一个类似问题的参考,建议使用void*指针或union ,但是我还没有完全理解它们是如何工作的。

No container types (such as std::any , std::optional , std::variant ) are allowed because I want to know if there is an alternative to those as well. 不允许使用任何容器类型(例如std::anystd::optionalstd::variant ),因为我想知道是否还有替代方法。

To add on, this is all in the name of curiosity . 补充一点,这一切都是出于好奇 Currently I am searching the optional and variant header files to know how the feature I'm asking for was implemented but no luck so far. 目前,我正在搜索optionalvariant头文件,以了解我所要求的功能是如何实现的,但到目前为止还算不上成功。

I'm hoping the platform here could have a practical solution to this potential problem. 我希望这里的平台可以为这个潜在问题提供实用的解决方案。

You can use a mix of template function and if constexpr (C++17): 您可以混合使用模板函数和if constexpr (C ++ 17):

template<typename T>
T valueOf() const {
    if constexpr(std::is_same<T, bool>) return _boolValueOf();
    else if constexpr(std::is_same<T, int>) return _intValueOf();
    else if constexpr(std::is_same<T, std::string>) return _std_stringValueOf();
}

Requires passing the type, but then the signature could be: 需要传递类型,但是签名可以是:

template<typename T>
T valueOf(const T& d) const {
    if constexpr(std::is_same<T, bool>) return _boolValueOf(d);
    else if constexpr(std::is_same<T, int>) return _intValueOf(d);
    else if constexpr(std::is_same<T, std::string>) return _std_stringValueOf(d);
}

High-level and recomended solution is std::any , std::variant , std::optional . 高级推荐的解决方案是std::anystd::variantstd::optional Low-level, hackish dangerous, final solution is union , void*, static_cast ... If you want neither, there is no more left to try. 低级,骇人听闻的危险,最终解决方案是unionvoid*, static_cast ……如果您都不想要,那就static_cast尝试了。 Do you finally want to do it in C++? 您最终想用C ++做到吗?

If are interested in the implementation of those high-level facilities, you can check the source code on open source implementations. 如果对这些高级工具的实现感兴趣,则可以检查开源实现的源代码。 But you will eventually find that those implementations device the low level constructs pointed above. 但是,您最终会发现,这些实现使用了上面指出的底层构造。

First to have different return types you need to use a template to differentiate the functions. 首先要具有不同的返回类型,您需要使用模板来区分功能。 Then you can call var(true).valueOf<bool>() for example. 然后,您可以例如调用var(true).valueOf<bool>() You will have to specify the template on every call so the compiler knows what function (and return type) to use. 您将必须在每次调用时指定模板,以便编译器知道要使用的函数(和返回类型)。 This can't be deduced on it's own. 不能单凭此推论。

Secondly the var.type is a string that can only be checked at runtime. 其次,var.type是只能在运行时检查的字符串。 So var(42).valueOf<bool>() compiles just fine. 因此var(42).valueOf<bool>()编译就很好。 You would have to check var.type against the template argument at runtime and throw an exception when the types don't match. 您将必须在运行时对照模板参数检查var.type,并在类型不匹配时引发异常。

Not an ideal design. 不是理想的设计。

For you valueOf function, imo, user-defined conversion is also a choice: 对于您的valueOf函数,imo也是用户定义的转换

operator std::string()
    {
        return primitive_value._char_pointer;
    }
    operator bool()
    {
        return primitive_value._bool;
    }
    operator int()
    {
        return primitive_value._int;
    }
    ......

Then you can use like this: 然后,您可以像这样使用:

var v1("hello");
var v2(true);
var v3(10);
std::string a = v1;
bool b = v2;
int c = v3;

std::cerr << static_cast<std::string>(v1) << '\n';
std::cerr << std::boolalpha << static_cast<bool>(v2) << '\n';
std::cerr << static_cast<int>(v3) << '\n';

If you still hope to use function, just add a operator() : 如果仍然希望使用函数,只需添加一个operator()

var
operator()()
{
    return *this;
}

Then you can: 那么你也能:

var v1("hello");
var v2(true);
var v3(10);
std::string a = v1();
bool b = v2();
int c = v3();

But still a little ugly, right? 但是还是有点难看吧? Just add your valueOf function: 只需添加您的valueOf函数:

var
valueOf()
{
    return *this;
}

Then: 然后:

var v1("hello");
var v2(true);
var v3(10);
std::string a = v1.valueOf();
bool b = v2.valueOf();
int c = v3.valueOf();

But these solutions have many limitions. 但是这些解决方案有很多局限性。 if constexpr provided by Matthieu Brucher is more powerful. if constexpr Matthieu Brucher提供的if constexpr更强大。 Just all about provide a idea here : ). 只是在这里提供一个想法:)。 But please note, unlike if constexpr, the ways I provided is not really multiple types return , just user-defined conversion. 但是请注意,与constexpr不同,我提供的方法实际上不是多种类型的return ,而是用户定义的转换。

Of course, there are more solutions, like sfinae(use enable_if and is_same in return type), or tag dispatch, but both of them require template 当然,还有更多解决方案,例如sfinae(在返回类型中使用enable_if和is_same)或标签分发,但它们都需要模板

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

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