VS2013 C++ C1001 error with std::tuple_cat

343 views Asked by At

I recently migrated a C++ code from VS2012 to VS2013. The code was compiling under VS2012 but VS2013 throws a C1001 Internal compiler error.

Specifically, the error points to the tuple.h file from the std library:

template<class... _Types1,
    class _Kx_arg,
    size_t... _Ix,
    size_t _Ix_next,
    class... _Types2,
    class... _Rest>
    struct _Tuple_cat2<tuple<_Types1...>, _Kx_arg, _Arg_idx<_Ix...>, _Ix_next,
        tuple<_Types2...>, _Rest...>
        : _Tuple_cat2<
            tuple<_Types1..., _Types2...>,
            typename _Cat_arg_idx<_Kx_arg,
                typename _Make_arg_idx<_Types2...>::type>::type,
            _Arg_idx<_Ix..., _Repeat_for<_Ix_next, _Types2>::value...>,
            _Ix_next + 1,
            _Rest...>
    {   // determine tuple_cat's return type and _Kx/_Ix indices
    };

My code calls the std::tuple_cat method in order to retrieve the type of concatenated tuples (note the partial specializations with the void type):

template <typename TupleA, typename TupleB>
    struct tuple_concatenator//yields the type of two concatenated tuples.
    {
        typedef decltype(std::tuple_cat(std::declval<TupleA>(),
                                        std::declval<TupleB>())) type;
    };
    template <typename TupleA>
    struct tuple_concatenator<TupleA, void>//yields the type of TupleA.
    {
        typedef TupleA type;
    };
    template <typename TupleB>
    struct tuple_concatenator<void, TupleB>//yields the type of TupleB.
    {
        typedef TupleB type;
    };
    template <>
    struct tuple_concatenator<void, void>
    {
        typedef void type;
    };

How would you configure VS2013 or rewrite the aforementioned code to avoid the C1001 error?

Thank you in advance for your help.

1

There are 1 answers

1
T.C. On

An ICE is always a compiler bug. File a bug with Microsoft (also, try and see if you can reproduce it on http://webcompiler.cloudapp.net/, which runs VS2015 RC).

std::tuple_cat is tricky to implement because it needs to be able to efficiently concatenate an arbitrary number of tuples - both the type and the value. But if you just need to concatenate two std::tuple<...> types, you don't need the complicated tuple_cat machinery; it's straightforward:

template <typename TupleA, typename TupleB>
struct tuple_concatenator;

template <class... Ts, class... Us>
struct tuple_concatenator<std::tuple<Ts...>, std::tuple<Us...>>
{
    typedef std::tuple<Ts..., Us...> type;
};

This should work just fine with your existing partial and full specializations for void.