返回未知类型的函数
class Test
{
public:
SOMETHING DoIt(int a)
{
float FLOAT = 1.2;
int INT = 2;
char CHAR = 'a';
switch(a)
{
case 1: return INT;
case 2: return FLOAT;
case 3: return CHAR;
}
}
};
int main(int argc, char* argv[])
{
Test obj;
cout<<obj.DoIt(1);
return 0;
}
现在,使用 a = 1 意味着我需要返回一个整数等知识,Doit() 是否可以返回可变数据类型的变量?
本质上,我用什么替换 SOMETHING ?
PS:我正在尝试寻找一种替代方法来返回包含这些数据类型的结构/联合。
class Test
{
public:
SOMETHING DoIt(int a)
{
float FLOAT = 1.2;
int INT = 2;
char CHAR = 'a';
switch(a)
{
case 1: return INT;
case 2: return FLOAT;
case 3: return CHAR;
}
}
};
int main(int argc, char* argv[])
{
Test obj;
cout<<obj.DoIt(1);
return 0;
}
Now, using the knowledge that a = 1 implies that I need to return an integer, etc., is there anyway Doit() can return a variable of variable data type?
Essentially, with what do I replace SOMETHING ?
PS: I'm trying to find a an alternative to returning a structure/union containing these data types.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
SOMETHING = void*
您必须转换返回的值,因此您必须知道返回的内容。
SOMETHING = void*
You have to cast the returned value, so you have to know what is returned.
您可以使用
boost::any
< /a> 或boost::variant
做你想做的事。我推荐boost::variant
因为您知道要返回的类型集合。这是一个非常简单的示例,尽管您可以使用
variant
做更多事情。检查参考以获取更多示例:)输出:
我将使用
boost::variant
而不是union
因为你不能在中使用非 POD 类型联盟。另外,如果您不知道正在处理的类型,则
boost::any
非常有用。否则,我会使用boost::variant
因为它更高效、更安全。回答编辑后的问题:如果您不想随代码一起发布
Boost
,请查看bcp
。来自同一链接的bcp
描述:You can use
boost::any
orboost::variant
to do what you want. I recommendboost::variant
because you know the collection of types you want to return.This is a very simple example, though you can do much more with
variant
. Check the reference for more examples :)The output:
I would use
boost::variant
instead of aunion
because you can't use non-POD types insideunion
. Also,boost::any
is great if you don't know the type you are dealing with. Otherwise, I would useboost::variant
because it is much more efficient and safer.Answering the edited question: If you don't want to ship
Boost
with your code, take a look atbcp
. The description ofbcp
from the same link:C++是强类型语言,没有未知类型的概念。您可以尝试使用 boost::any,它可以(某种程度上)指定任何类型。然而,我会质疑你的功能的设计。
C++ is a strongly-typed language, and has no concept of an unknown type. You could try using boost::any, which can (sort of) specify any type. I would question the design of your function, however.
如果您知道编译时的类型,则可以使用模板。如果类型取决于运行时,则不能选择使用模板。
If you know type at compile time you could use templates. If type depends on run-time, then using templates is not an option.
您似乎对这里的术语有点困惑。
首先,我们将其称为 ISO C++,好吗?它于 1998 年由 ISO 标准化,从那时起,这就是人们在谈论“标准 C++”时所指的。
现在,“ANSI C++ 解决方案”是什么意思?
我无法想象您会得到什么样的“证明” 。 C++ 是散文形式的文档,它不是一个数学方程,除非通过“去阅读标准”来证明。语言或标准库中的内容很容易 - 只需指出标准中的描述位置即可,但要证明不存在某些内容基本上是不可能的 - 除非枚举每个<。 /em> 标准的一句话,并记录它们都没有描述您正在寻找的内容,并且我怀疑您会找到愿意为您做的事情
无论如何,正确的标准 。 C++ 解决方案是使用Boost。
这不是一个重量级的解决方案。 Boost 非常轻量级,因为您可以准确包含您需要的位,而不依赖于库集合的其余部分。
根据您的描述(面向广泛用户群的轻型应用程序),没有理由不使用 Boost。它可以简化您的代码并减少因尝试重新发明轮子而导致的错误数量。分发编译后的可执行文件时,成本为零。与 Boost 的大部分内容一样,
Boost.Any
库仅包含头文件,并且只需编译到可执行文件中即可。无需分发单独的库。尝试重新发明轮子不会有任何收获。您的可执行文件不会更小或更高效,但它会出现更多错误。
我敢打赌,您自制的解决方案将不是是 ANSI C++。它将依赖于某种形式的未定义行为。如果您想要 ANSI-C++ 解决方案,那么最好的选择是 Boost。
You seem a bit confused about the terminology here.
First, let's call it ISO C++, shall we? It was standardized by ISO in 1998, and since then, that is what people have referred to when talking about "standard C++".
Now, what do you mean by an "ANSI C++ solution"?
I can't imagine what kind of "proof" you'd be looking for. C++ is a document in prose form. It is not a mathematical equation. It can not be "proven", except by saying "go read the standard". Proving that something is defined in the language or in the standard library is easy -- simply point out where in the standard it is described. But proving that something isn't there is basically impossible -- except by enumerating every single sentence of the standard, and document that none of them describe what you're looking for. And I doubt you'll find anyone willing to do that for you.
Anyway, the correct standard C++ solution is to use Boost.
It is not a heavy-weight solution. Boost is pretty lightweight in that you can include exactly the bits you need, with no dependencies on the rest of the library collection.
From what you've described (a light application for a broad user base), there is zero reason not to use Boost. It can simplify your code and reduce the number of bugs caused by attempting to reinvent the wheel. When distributing the compiled executable, it has zero cost. The
Boost.Any
library is, like much of Boost, header-only, and is simply compiled into your executable. No separate libraries have to be distributed.There is nothing to be gained by trying to reinvent the wheel. Your executable will be no smaller or more efficient, but it will be more buggy.
And I'm willing to bet that your home-brewed solution will not be ANSI C++. It will rely on some form of undefined behavior. If you want an ANSI-C++ solution, your best bet is Boost.
使用 boost::any:
Use boost::any:
实现这样的事情的通常方法是 C,它并不总是在 C++ 中工作,而是使用联合和类型字段:
当可能的值类型之一是具有非 - 的类时,这在 C++ 中不起作用。简单的构造函数,因为并不总是清楚应该调用哪个构造函数。 Boost.Variant 使用了更复杂的版本为 C++ 中的任何值类型提供这种构造的方法。
The usual way to achieve something like this is C, which doesn't always work in C++, is with a union and a type field:
This doesn't work in C++ when one of the possible value types is a class with a non-trivial constructor, because it wouldn't always be clear which constructor should be called. Boost.Variant uses a more complex version of this approach to provide this kind of construct for any value types in C++.
您可以使用包含指向您想要返回的值的
void*
以及指示要返回的对象的大小的size_t
的结构。像这样的事情:记住
void*
应该指向驻留在堆上的值(即使用new
或malloc
动态分配)并且调用者应该负责释放分配的对象。话虽如此,我认为总体来说这是一个坏主意。
编辑:您可能还需要考虑包含一个标志,指示上述结构中返回的内容,以便调用者可以理解它,除非调用者知道期望的类型。
You could use a struct containing a
void*
pointing to the value you want returned along with asize_t
that indicates the size of the object being returned. Something like this:Remember that the
void*
should point to a value residing on the heap (i.e. dynamically allocated usingnew
ormalloc
) and the caller should take care of freeing the allocated object.Having said that, I think it's a bad idea overall.
Edit: You may also want to consider including a flag indicating what was returned in the above structure so that the caller can make sense of it, unless the caller knows what type to expect.
你可以使用联合:
You could use a union:
Adobe Source Libraries 还具有
adobe::any_regular_t
,它允许您可以存储任何类型,只要它符合 常规 概念即可。您可以像使用boost::any
一样包装返回值。 (链接页面上还有关于adobe::any_regular_t
与boost::any
有何不同的文档 - 当然,您选择的类型应该取决于你的代码。)The Adobe Source Libraries also has
adobe::any_regular_t
, which allows you to store any type as long as it models the Regular concept. You would wrap your return value much the same way you would withboost::any
. (There is also documentation on the linked page as to howadobe::any_regular_t
differs fromboost::any
-- of course the type you pick should depend on the requirements of your code.)您可以通过引用传递,并进行类型保存并检查它是否同时工作,也不会涉及任何额外的库(您的 ansi C++ 解决方案):
...
我发现这个解决方案在设计方面通常更干净。不幸的是,函数签名不允许多种类型作为返回类型,但这样您就可以传递任何内容。
You could pass by reference instead and be typesave and check if it worked at the same time, would not involve any additional library either (your kind of ansi C++ solution):
...
I find this solution often more clean in terms of design. It's unfortunate that funciton signatures don't allow multiple types as return types, but this way you can pass anything.
从 C++17 开始,有
std::any
< /a> 和std::variant
,这意味着您不需要第三方库。根据@Arak 的回答,代码将进行如下修改。As of C++17 there is
std::any
andstd::variant
, which means you do not need third party library for this. From @Arak's answer the code will be modified a bit as below.如果用户知道放入的内容,您可以使用模板来解决此问题。如果没有,我想不出任何解决办法。
If the user knows what is put in, you could use a template to fix this. If not, I can't think of any solution.
我认为问题出在这个功能设计上。你尝试过超载吗?
在 DoIt 函数内部,您可以放置更多代码并让它们调用其他函数以避免重复代码。
I think the problem is about this function design. Have you tried overloading?
Inside DoIt functions you can place more code and make them call other functions for not repeating code.