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;
}
现在,使用知识,一个= 1意味着我需要返回的整数,等等,是有反正大一()可以返回变量的数据类型的变量?
从本质上讲,有什么我取代的东西 ?
PS:我试图找到一个替代返回包含这些数据类型的结构/联合。
Answer 1:
您可以使用boost::any
或boost::variant
做你想做什么。 我推荐boost::variant
,因为你知道你要返回值类型的集合。
这是一个非常简单的例子,虽然你可以做更多的variant
。 检查更多的例子参考:)
#include "boost/variant.hpp"
#include <iostream>
typedef boost::variant<char, int, double> myvariant;
myvariant fun(int value)
{
if(value == 0)
{
return 1001;
}
else if(value == 1)
{
return 3.2;
}
return 'V';
}
int main()
{
myvariant v = fun(0);
std::cout << v << std::endl;
v = fun(1);
std::cout << v << std::endl;
v = fun(54151);
std::cout << v << std::endl;
}
输出:
1001
3.2
V
我会用boost::variant
,而不是union
,因为你不能使用内部非POD类型的union
。 此外, boost::any
是巨大的,如果你不知道你正在处理的类型。 否则,我会用boost::variant
,因为它是更有效,更安全。
在回答编辑的问题:如果你不想出货Boost
你的代码,看看bcp
。 的描述bcp
从相同的链接:
bcp实用工具是用于提取加速的子集的工具,它是谁想要单独分发他们的图书馆从升压,以及谁想要分发加速的一个子集与他们的应用程序加速用户加速作家有用。
BCP也可以在其上提升您的部分代码依赖于,并通过这些依赖使用何种许可报告。
Answer 2:
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.
Answer 3:
如果你知道在编译时的类型,你可以使用模板。 如果类型取决于运行时,则使用模板是不是一种选择。
class Test
{
template<int> struct Int2Type {};
template<> struct Int2Type<1> { typedef int value_type; };
template<> struct Int2Type<2> { typedef float value_type; };
template<> struct Int2Type<3> { typedef char value_type; };
public:
template<int x> typename Int2Type<x>::value_type DoIt() {}; // error if unknown type used
template<> typename Int2Type<1>::value_type DoIt<1>() { return 2; };
template<> typename Int2Type<2>::value_type DoIt<2>() { return 1.2f; };
template<> typename Int2Type<3>::value_type DoIt<3>() { return 'a'; };
};
int main()
{
Test obj;
cout << obj.DoIt<2>();
return 0;
}
Answer 4:
使用的boost ::任何 :
boost::any DoIt(int a)
{
float FLOAT = 1.2;
int INT = 2;
char CHAR = 'a';
switch(a)
{
case 1: return boost::any(INT);
case 2: return boost::any( FLOAT);
case 3: return boost::any( CHAR);
}
}
Answer 5:
通常的方法来实现这样的事情是C,这并不总是在C ++中工作,为联合和类型字段:
enum SomeType { INT, FLOAT, CHAR };
struct Something
{
SomeType type;
union
{
int i;
float f;
char c;
};
};
Something DoIt(int a)
{
Something s;
switch (a)
{
case 1:
s.type = INT;
s.i = 2;
break;
case 2:
s.type = FLOAT;
s.f = 1.2;
break;
case 3:
s.type = CHAR;
s.c = 'a';
break;
default:
// ???
}
return s;
}
这并不用C ++运行时可能的值类型之一是一个不平凡的构造函数的类,因为它并不总是清楚哪些构造函数被调用。 Boost.Variant使用这种方法的一个更复杂的版本,在C ++的任何值类型提供了这种结构的。
Answer 6:
你可以使用含有一个struct void*
指向你想要一个一起返回值size_t
指示正在返回的对象的大小。 事情是这样的:
struct Something {
void *value;
size_t size;
};
请记住, void*
应指向驻留在堆的值(即使用动态分配的new
或malloc
)和呼叫方应释放分配对象的照顾。
话虽如此,我认为这是整个一个坏主意。
编辑:您可能还需要考虑包括指示哪些是在上述结构中返回,以便调用者可以理解它,除非调用者知道会发生什么类型的标志。
Answer 7:
编辑:提高::任何使用BCP(感谢阿拉克)似乎是迄今为止最好的解决办法,但它可以证明(在某种程度上)不存在任何ANSI C ++解决这个问题?
你似乎对这里的术语有点混乱。
首先,让我们把它叫做ISO C ++,好吗? 它是由ISO 1998规范,从那时起,这就是人们称之为谈到何时“标准C ++”。 现在,你是什么意思的“ANSI C ++的解决方案”是什么意思?
- 该编译干净地仅使用ANSI(或ISO)C ++的溶液? 如果是这样,升压是 ANSI C ++溶液
- 在ANSI C ++标准库中已经实施的解决方案? 如果是的话没有,没有这样的解决方案存在(并没有“证明”,除了“经过语言标准阅读,看看你是否能找到这样的类。如果不能,它不存在。”
- 一个解决方案,你可以只使用ANSI C ++实现自己 。 那么答案是“是的,你可以去源代码复制升压”。
我无法想象什么样的“证明”,你会寻找。 C ++是散文形式的文件。 这不是一个数学公式。 说“去阅读标准”不能“证明”除外。 证明的东西是在语言或标准库定义是很容易-在标准中描述了简单地指出。 但是,证明自己是不是有基本上是不可能的-除了通过列举标准的每一个句子,而他们没有描述你要寻找的文件。 我怀疑你会发现任何人都愿意为你做的 。
无论如何,正确的标准C ++解决方案是使用升压。 这不是一个重量级的解决方案。 升压是,你可以包括正是你所需要的位,对图书馆藏书的其余部分没有依赖性非常轻巧。
从你描述的内容(为广泛的用户基础轻应用程序),还有零理由不使用升压。 它可以简化您的代码,并试图通过推倒重来减少由于错误的数量。 当分配编译的可执行文件,它具有零成本。 该Boost.Any
库,像很多的Boost,仅邮件头,并简单编译成可执行文件。 没有单独的图书馆有分发。
没有什么可以试图另起炉灶获得。 你的可执行文件将不小的或更有效,但它会更马车。
而且我敢打赌,你的家中自酿的解决方案不会是ANSI C ++。 它将依赖某种形式的不确定的行为。 如果你想要一个ANSI-C ++的解决方案,最好的办法是加速。
Answer 8:
你可以使用一个联盟:
typedef union {
int i;
float f;
char c;
} retType;
retType DoIt(int a){
retType ret;
float FLOAT = 1.2;
int INT = 2;
char CHAR = 'a';
switch(a)
{
case 1: ret.i = INT; break;
case 2: ret.f = FLOAT; break;
case 3: ret.c = CHAR; break;
}
return ret;
}
Answer 9:
Adobe的源库也有adobe::any_regular_t
,它允许你只要存储任何类型的,因为它的车型经常概念。 你会换你的返回值多少你会用同样的方式boost::any
。 (也有链接的页面,以如何对文档adobe::any_regular_t
从不同boost::any
-当然你选择应取决于你的代码的需求类型)
Answer 10:
您可以通过引用传递来代替,并typesave并检查它是否工作在同一时间,将不涉及任何额外的库是(你的那种ANSI C ++的解决方案):
bool DoIt (int i, int & r1)
{
if (i==1) {r1 = 5; return true}
return false;
}
bool DoIt (int i, double & r2)
{
if (i==2) {r2 = 1.2; return true}
return false;
}
...
我觉得这个解决方案往往在设计方面更干净。 这是不幸的功能可按签名不允许多个类型为返回类型,但这样一来,你可以通过任何东西。
Answer 11:
如果用户知道什么放进去,你可以使用模板来解决这个问题。 如果没有,我想不出任何解决方案。
Answer 12:
我认为这个问题是有关该功能的设计。 您是否尝试过超载?
class Test
{
public:
int DoIt(int a) {
int INT = 2;
return INT;
}
float DoIt(float a) {
float FLOAT = 1.2;
return FLOAT;
}
char DoIt(char a) {
char CHAR = 'a';
return CHAR;
}
};
int main(int argc, char* argv[])
{
Test obj;
//....
switch(a)
case 1:
cout<< obj.DoIt(1);
break;
case 2:
cout<< obj.DoIt(1.01);
break;
case 3:
cout<< obj.DoIt("1");
break;
return 0;
}
DOIT内部功能您可以将更多的代码,使他们调用其它函数不重复的代码。
Answer 13:
SOMETHING =无效*
你必须转换返回的值,所以你必须要知道什么是返回。
void* 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;
}
}
文章来源: Function which returns an unknown type