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

时间:2018-11-19 12:32:08

标签: c++ c++17

是否有任何方法(传统方法或否方法)在函数的多个指定返回类型之间进行选择。例如:

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

有一个类似问题的参考文献here,我建议使用void*指针或union的指针,但是我还没有完全理解它们是如何工作的。

不允许使用任何容器类型(例如std::anystd::optionalstd::variant),因为我想知道是否还有替代方法。

要添加,所有这些都是好奇心的名称。目前,我正在搜索optionalvariant头文件,以了解我所要求的功能是如何实现的,但到目前为止还算不上成功。

我希望这里的平台可以为这一潜在问题提供切实可行的解决方案。

4 个答案:

答案 0 :(得分:8)

您可以混合使用模板函数和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();
}

需要传递类型,但是签名可以是:

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

答案 1 :(得分:2)

高级和推荐的解决方案是std::anystd::variantstd::optional。低级,骇人听闻的危险最终解决方案是unionvoid*, static_cast ... 如果您都不想要,那就别无所求了。您最终想要用C ++做到吗?

如果对那些高级工具的实现感兴趣,则可以检查开源实现的源代码。但是您最终会发现这些实现使用了上面指出的低级构造。

答案 2 :(得分:1)

首先要具有不同的返回类型,您需要使用模板来区分功能。然后,您可以致电var(true).valueOf<bool>()。您将必须在每次调用时指定模板,以便编译器知道要使用的函数(和返回类型)。不能单凭此推论。

第二,var.type是只能在运行时检查的字符串。因此var(42).valueOf<bool>()编译就可以了。您将必须在运行时对照template参数检查var.type,并在类型不匹配时引发异常。

不是理想的设计。

答案 3 :(得分:0)

对于您的valueOf函数,imo,user-defined conversion也可以选择:

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

然后您可以像这样使用

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

如果您仍然希望使用函数,只需添加一个operator()

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

然后您可以:

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

但是还是有点难看吧?只需添加您的valueOf函数:

var
valueOf()
{
    return *this;
}

然后:

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

但是这些解决方案有很多局限性。 Matthieu Brucher提供的if constexpr功能更强大。只是在这里提供一个想法:)。 但是请注意,与constexpr不同,我提供的方法并不是真正返回多种类型,只是用户定义的转换。

当然,还有更多解决方案,例如sfinae(在返回类型中使用enable_if和is_same)或标签分发,但它们都需要模板