Как можно написать функцию С++, которая при определенных условиях возвращает значения разных типов?
Как можно написать функцию С++, которая при определенных условиях возвращает значения разных типов?
Как можно написать функцию С++, которая при определенных условиях возвращает значения разных типов?
C++ это строго типизированный язык, и функция возвращает только тот тип, что указан в сигнатуре (объявлении функции)
Хотя можно возвращать указатель на пустой тип void*
и на свой страх и риск конвертировать в нужный тип, либо использовать возможности наследования, и переопределять возвращаемый тип функции в дочерних классах. Но все таки это будут разные функции с одним названием, а не одна и та же функция
Не до конца понял вопрос, можно сделать через шаблоны вот так:
#include <iostream>
using namespace std;
template<typename Type>
Type func(Type a){
return a;
}
int main(){
cout<<func<int>(5)<<endl;
cout<<func<char>(5)<<endl;
cout<<func<double>(5)<<endl;
}
Либо через C макросы, но это плохая идея так как дико ненадежно:
#include <iostream>
using namespace std;
char f() { return 5; }
int main()
{
#define fi(...) ((int)f(__VA_ARGS__))
//fi - макрос, (int) тип функции f, __VA_ARGS__ - макрос для аргументов, но нужно занести хотя бы один
#define fd(...) ((double)f(__VA_ARGS__))
#define fc(...) ((char)f(__VA_ARGS__))
cout << fi() << endl;
cout << fd() << endl;
cout << fc() << endl;
return 0;
}
Возвращаемы тип менять нельзя. Но можно в один тип вместить много разных с помощью union
.
Чтобы тип возвращаемого значения было просто определить можно возвращать структуру с номером типа и значение типа union
которое может в себе вместить все возможные типы.
Вот пример из трёх типов : число, Си строка, C++ объект класса string
# include <string>
# include <cstring>
# include <iostream>
struct Ret {
enum Ty { Int , Stri , stdStri } ;
Ty t ;
union {
int i ;
char * st ;
std :: string ss ;
} ;
Ret():t{Int}{}
Ret(Ret const & );
Ret & operator = ( Ret const & ) ;
~Ret();
private :
void Free ( ) ;
} ;
Ret fun ( Ret const & ) ;
int main ( ) {
Ret i ;
i . t = Ret :: Ty :: Int ;
i . i = 7 ;
Ret ri = fun ( i ) ;
if ( ri . t == Ret :: Ty :: Int ) {
std :: cout << "r . i = " << ri . i << std :: endl ;
}
Ret s ;
s . t = Ret :: Ty :: Stri ;
{ char const * const s0 = "def" ;
size_t const l = strlen ( s0 ) ;
s . st = new char [ l + 1 ] ;
strncpy ( s . st , s0 , l + 1 ) ;
}
Ret rs = fun ( s ) ;
if ( rs . t == Ret :: Ty :: Stri ) {
std :: cout << "rs . st = `" << rs . st << "`" << std :: endl ;
}
Ret x ;
x . t = Ret :: Ty :: stdStri ;
new ( & x . ss ) std :: string ( "abc" ) ;
Ret r = fun ( x ) ;
if ( r . t == Ret :: Ty :: stdStri ) {
std :: cout << "r . ss = `" << r . ss << "`" << std :: endl ;
}
}
Ret fun ( Ret const & r ) {
Ret re { r } ;
switch ( r . t ) {
case Ret :: Ty :: Int :
re . i = r . i + 1 ;
break ;
case Ret :: Ty :: Stri :
{ char * i ;
for ( i = re . st ; * i ; ++ i )
* i = toupper ( * i ) ;
* i = '\00' ;
}
break ;
case Ret :: Ty :: stdStri :
for (auto & c: re . ss)
c = toupper(c);
break ;
}
return re ;
}
Ret:: Ret(Ret const & x):t{Int}{
( * this ) = x ;
}
Ret & Ret :: operator = ( Ret const & x ) {
Free ( ) ;
t = x . t ;
switch ( x . t ) {
case Int :
i = x . i ;
break ;
case Stri :
{ size_t const l = strlen ( x . st ) ;
st = new char [ l + 1 ] ;
strncpy ( st , x . st , l + 1 ) ;
}
break ;
case stdStri :
new ( & ss ) std :: string ( x . ss ) ;
break ;
}
return * this ;
}
Ret:: ~Ret(){
Free ( ) ;
}
void Ret :: Free ( ) {
switch ( t ) {
case Int :
break ;
case Stri :
delete [ ] st ;
break ;
case stdStri :
ss . ~ basic_string ( ) ;
break ;
}
t = Int ;
}