Getting tuple element by type (pre C++0x)

895 views Asked by At

I have a templated class that holds a tuple and want to be able to retrieve the elements by type at compile time. To simplify things the container class is restricted to a maximum of three entries:

template< class U = null_type, class V = null_type, class W = null_type >
class TupleContainer {
public:

    template< class ReturnT >
    ReturnT& getElementbyType() {
        return get< ReturnT >(data_);
    }

private:
    boost::tuple< U, V, W > data_;
}

Reading the answers to Get index of a tuple element's type and For std::tuple, how to get data by type, and how to get type by index? I achieved this through a recursive visitor approach and it works just fine using the GNU C++ compiler with c++11 features.

template< int Index, class Search, class First, class... Types >
struct get_internal
{
    typedef typename get_internal< Index + 1, Search, Types...>::type type;
    static constexpr int index = Index;
};

template< int Index, class Search, class... Types >
struct get_internal< Index, Search, Search, Types... >
{
    typedef get_internal type;
    static constexpr int index = Index;
};

template< class T, class... Types >
T& get( std::tuple< Types... >& tuple )
{
    return std::get< get_internal< 0, T, Types... >::type::index >(tuple);
}

I now have to port my code to windows. Due to restrictions of some external library I'm bound to use Visual Studio 2010 which seems to not support variadic templates.

I'm sure there is a workaround (since boost::tuple is also available without the support of variadic templates) but I'm still new to this whole template metaprogramming topic and have not found a solution yet.

So does anybody know a way to solve this problem without variadic templates working in Visual Studio 2010?

BTW: The visitor approach works well even with tuples with far more than three elements. The container will be restricted to 3 or 4 tuple elements so I wouldn't even mind hardcoding the indexes into my implementation.

1

There are 1 answers

0
Daniel Frey On BEST ANSWER

You don't need the preprocessor to generate a large number of overloads, just adapt your get_internal approach to work without variadic templates. They need to have a similar amount of parameters like TupleContainer:

template< class R, class U, class V, class W >
struct getIndex
{
    static const int value = getIndex< R, V, W, null_type >::value + 1;
};

template< class R, class V, class W >
struct getIndex< R, R, V, W >
{
    static const int value = 0;
};

template< class R >
struct getIndex< R, null_type, null_type, null_type >
{
    // let it fail if the type is not found and avoid infinite recursion
};

and now you can use

template< class R >
R& getElementByType() {
    return get< getIndex< R, U, V, W >::value >(data_);
}