是否有任何方法(传统方法或否方法)在函数的多个指定返回类型之间进行选择。例如:
/* 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::any
,std::optional
,std::variant
),因为我想知道是否还有替代方法。
要添加,所有这些都是好奇心的名称。目前,我正在搜索optional
和variant
头文件,以了解我所要求的功能是如何实现的,但到目前为止还算不上成功。
我希望这里的平台可以为这一潜在问题提供切实可行的解决方案。
答案 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::any
,std::variant
,std::optional
。低级,骇人听闻的危险最终解决方案是union
,void*,
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)或标签分发,但它们都需要模板