Boost logo

Boost :

Subject: [boost] [offtopic] C++11 useful trick
From: Eric Niebler (eric_at_[hidden])
Date: 2012-07-01 19:20:19


I recently ran into a limitation in recursive functions that make use of
decltype in trailing return types. I've come up with a work-around that
I think is a little non-obvious, so I thought I'd share.

The problem came up while trying to implementing something like a
variadic back() function. The "obvious" implementation doesn't work:

    template<typename T>
    T back(T && t)
    {
        return t;
    }

    template<typename T, typename ...U>
    auto back(T && t, U &&... u)
        -> decltype(::back(static_cast<U &&>(u)...)) // ERROR
    {
        return ::back(static_cast<U &&>(u)...);
    }

    int main()
    {
        int i = ::back(1,2,3);
    }

The problem occurs on the line marked "HERE". Trouble is, the variadic
"back" function is not yet in scope until after the return type.
However, we'd like to use it when specifying the return type.

The solution uses a default function template parameter to make the
::back symbol dependent, thereby deferring it's lookup until phase 2,
when the symbol is visible. Check it:

    struct S
    {
        template<typename T>
        static T back(T && t)
        {
            return t;
        }

        template<typename T, typename ...U, typename Impl = S>
        static auto back(T && t, U &&... u)
            -> decltype(Impl::back(static_cast<U &&>(u)...))
        {
            return Impl::back(static_cast<U &&>(u)...);
        }
    };

    int main()
    {
        int i = S::back(1,2,3);
    }

The trick is the "typename Impl = S" followed by a (now dependent)
invocation of Impl::back. Voila.

Apologies if this is a known technique, and I'm spamming the list with
old news. It's news to me.

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk