TreeExplorer: identify yet another subtle type inference problem

surprising behaviour encountered while covering more cases

...obviously the return type of ExpandFunctor::operator()
was inferred as value, even while the invoked functor, from which
this type was deduced, clearly returns a reference.

Solution is simple not to rely on inference, moreover since we know
the exact type in the enclosing scope, thanks to the refactoring which
made this ExpandFunctor a nested class

NOTE:
as it turned out, this is not a compiler bug,
but works as defined by the language:
on return type inference, the detected type is decayed,
which usually helps to prevent returning a reference to a temporary
This commit is contained in:
Fischlurch 2017-11-27 02:07:04 +01:00
parent 6667a51a61
commit 77c3226948
2 changed files with 25 additions and 1 deletions

View file

@ -221,3 +221,27 @@ Thus -- as of 9/2014 -- the _rules of the game_ are as folows
to variadic templates and `std::tuple`
Type inference
~~~~~~~~~~~~~~
Generally speaking, the use of `auto` and type inference has the potential to significantly improve readability of
the code. Indeed, this new language feature is what removed most of the clumsiness regarding use of the Lumiera
Forward Iterator concept. There are some notable pitfalls to consider, though
- the `decltype(...)` operator is kind-of ``overloaded'', insofar it supports two distinct usages
* to find out the type of a given _name_
* to deduce the type of a given _expression_
- and the `auto` type inference does not just pick up what `decltype` would see -- rather, it applies its own
preferences and transformations (which does make much sense from a pragmatic perspective)
* a definition with `auto` type specification always prefers to create an object or data element. This is very much
in contrast to the usual behaviour of the C++ language, which by default prefers a reference as result type of
expression evaluation.
* return type deduction always _decays_ the inferred type (similar as `std::decay<T>::type` does). Which means,
functions and arrays become pointers, and a _reference_ becomes a _value_. Given the danger of returning a
dangling reference to local storage, the latter is a sensible default, but certainly not what you'd expect
when just passing the result from a delegate function (or lambda!).

View file

@ -364,7 +364,7 @@ namespace lib {
function<Sig> expandFun;
template<typename ARG>
auto
Res
operator() (ARG& arg)
{
auto accessArg = ArgAccessor<ARG>::build();