Topic: Finding the return type of a function, hassles with traits.
Author: "Steve R. Karmesin" <ssr@cacr.caltech.edu>
Date: 1996/10/24 Raw View
As has been pointed out in the recent thread on Return Value and
Function's Signature, the name of a function and the types of its
arguments fully specifies the return type of the function.
A problem I'm coming across is that I want to know that type. Consider
the following code:
class A {};
class B {};
class C {};
class AB {};
class BC {};
class AC {};
class BA {};
class CB {};
class CA {};
AB f(A,B) { return AB(); }
AC f(A,C) { return AC(); }
BC f(B,C) { return BC(); }
BA f(B,A) { return BA(); }
CA f(C,A) { return CA(); }
CB f(C,B) { return CB(); }
It defines three types A, B and C, and three functions that take
permuatations of A, B and C and return types that depend on the
arguments.
Now suppose I want to define a template function of two arguments that
uses the function f on those arguments. It might look like
template<class T1, class T2>
g(T1 t1, T2 t2)
{
return f(t1,t2);
}
Note that I haven't specified the return type of g. As far as I know,
there is no mechanism in the C++ language to extract the return type of
f(T1,T2), so I can't figure out the return type g should have even
though it fully specified by the text of the program.
Now, I can certainly hack around this by introducing a parallel set of
trait classes to store the return types of f:
template<class T1, class T2> class f_return {};
template<> class f_return<A,B> { public: typedef AB type; };
template<> class f_return<A,C> { public: typedef AC type; };
template<> class f_return<B,C> { public: typedef BC type; };
template<> class f_return<B,A> { public: typedef BA type; };
template<> class f_return<C,A> { public: typedef CA type; };
template<> class f_return<C,B> { public: typedef CB type; };
and then I can write g:
template<class T1, class T2>
f_return<T1,T2>::type g(T1 t1, T2 t2)
{
return f(t1,t2);
}
There are a couple of problems with this:
1. A set of parallel classes like this is inherently error prone because
it repeats information. Any change to the function(s) f requires a
change to the trait class f_return.
2. Separate libraries are unlikely to use the same notation for setting
up a trait class like this, making it impossible to rely on being able
to figure out the return type of classes that I don't control. This
kills may forms of reuse.
3. Instead of writing functions for f I could write functors that you
could query about the return types. This makes 1. less of a problem
because the specifications are in the same place, but 2. is still a
problem because separate libraries won't use the same notation.
It seems to me that this could be solved with an operator such as
'typeof' which would return the type of a function call or perhaps a
larger expression. I would then be able to write g as:
template<class T1, class T2>
typeof(f(T1,T2)) g(T1 t1, T2 t2)
{
return f(t1,t2);
}
or something like that.
I'm curious about a couple of things:
1. Is there some language feature that I've overlooked that would let me
do this sort of thing? Note that I'm looking for a way to do it fully
at compile time, not using RTTI. This is for heavily templated
applications.
2. Was a language feature like this discussed by the standards committee
and rejected? If so, what were the reasons for its rejection?
--
Steve R. Karmesin
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]