4

So I'm given a std::tuple<T...>, and I want to create a function pointer accepting T..., currently this is what I've got;

template<typename... Arguments>
using FunctionPointer = void (*)(Arguments...);

using FunctionPtr = FunctionPointer<typename std::tuple_element<0, V>::type,
                                    typename std::tuple_element<1, V>::type,
                                    typename std::tuple_element<2, V>::type>;

However I can't seem to find a way to do this, without manually entering each and every index from 0, ..., tuple_size<V>::value. The FunctionPtr is defined in a context, where V=std::tuple<T...> (also there is already a variadic template (hence I can't just pass T... directly))

I guess I need to generate some list of indexes, and do some black magic..

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
Skeen
  • 4,614
  • 5
  • 41
  • 67

2 Answers2

5

Here is a possible solution:

#include <tuple>

// This is what you already have...
template<typename... Arguments>
using FunctionPointer = void (*)(Arguments...);

// Some new machinery the end user does not need to no about
namespace detail
{
    template<typename>
    struct from_tuple { };

    template<typename... Ts>
    struct from_tuple<std::tuple<Ts...>>
    {
        using FunctionPtr = FunctionPointer<Ts...>;
    };
}

//=================================================================
// This is how your original alias template ends up being rewritten
//=================================================================
template<typename T>
using FunctionPtr = typename detail::from_tuple<T>::FunctionPtr;

And here is how you would use it:

// Some function to test if the alias template works correctly
void foo(int, double, bool) { }

int main()
{
    // Given a tuple type...
    using my_tuple = std::tuple<int, double, bool>;

    // Retrieve the associated function pointer type...
    using my_fxn_ptr = FunctionPtr<my_tuple>; // <== This should be what you want

    // And verify the function pointer type is correct!
    my_fxn_ptr ptr = &foo;
}
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • Amazing! - I've been hacking at it for quite a while now, and you just fixed it in a blink of an eye! - It seems I still need much practice with tuples and variadic templates ;) – Skeen Mar 07 '13 at 11:42
  • @Skeen: That's normal, it takes a while to get the hang of it – Andy Prowl Mar 07 '13 at 11:43
  • @AndyProwl: do you know if it is allowed to keep the original definition of `FunctionPtr` and add a *specialization* for tuples ? – Matthieu M. Mar 07 '13 at 12:23
  • @MatthieuM.: You mean partially specializing the alias template? No, that is forbidden... – Andy Prowl Mar 07 '13 at 12:26
  • 2
    @MatthieuM.: The standard reference is 14.5/3: "*Because an alias-declaration cannot declare a template-id, it is not possible to partially or explicitly specialize an alias template.*" – Andy Prowl Mar 07 '13 at 12:32
  • @AndyProwl: Thanks! That's exactly what I meant. – Matthieu M. Mar 07 '13 at 14:02
5

A simple trait might do the trick:

#include <tuple>

template <typename> struct tuple_to_function;

template <typename ...Args>
struct tuple_to_function<std::tuple<Args...>>
{
    typedef void (*type)(Args...);
};

Usage:

typedef std::tuple<Foo, Bar, int> myTuple;

tuple_to_function<myTuple>::type fp; // is a void (*)(Foo, Bar, int)
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084