Fatal error with template type-alias

Viewed 347

Note: scroll to bottom of question for update.

When compiling my C++ program with Visual Studio 2017 (using /std:c++latest), I get an error that reads:

'thrust::tuple_element': template parameter 'N': 'i': a variable with non-static storage duration cannot be used as a non-type argument

The portion of code that produces the error is the following:

namespace thrust
{
template<size_t i, class... Types>
using tuple_element_t = typename tuple_element<i,Types...>::type;

The error is produced specifically by the line that begins with using. The link that Visual Studio provides to explain the error (https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-2/compiler-error-c2971) is rather straightforward, explaining that a local variable cannot be used as a template argument. However, I do not understand how that error applies in this case - the parameter i was declared as shown in the code above as size_t i in what I understand to be the normal way to define templates.

Furthermore, after this error is produced, Visual Studio creates a brief pop-up that reads

Microsoft (R) C/C++ Optimizing Compiler has stopped working

Windows is checking for a solution to the problem...

and afterwards in the error list a second error reads "unable to recover from previous error(s); stopping compilation". This fatal error and the above described error are the only two errors.

Why is the compiler producing the first error and how can I fix it? And why might this error cause the compiler to crash like this?

By the way, the tuple_element that appears in the error-producing code is from the Thrust parallel algorithms library (see https://thrust.github.io/doc/structthrust_1_1tuple__element.html).

Additional note: the usage of tuple_element_t occurs as shown below.

namespace tuple_repeat_ns
{
template<typename T, typename IndexSequence>
struct tuple_repeat_helper;

template<typename T, size_t... I>
struct tuple_repeat_helper<T, std::index_sequence<I...>>
{
    using type = tuple<tuple_element_t<I-I,tuple<T>>...>;
};

template<typename T, size_t N>
struct tuple_repeat_traits : tuple_repeat_helper<T,std::make_index_sequence<N>>
{
    using typename tuple_repeat_helper<T,std::make_index_sequence<N>>::type;
};

template<size_t I, typename T>
auto tuple_repeat_identity(const T& t)
{
    return t;
}

template<typename T, size_t... I>
auto tuple_repeat(const T& t, std::index_sequence<I...>)
{
    return make_tuple(tuple_repeat_identity<I>(t)...);
}
}

template<typename T, size_t N>
using tuple_repeat_t = typename tuple_repeat_ns::tuple_repeat_traits<T, N>::type;

template<size_t N, typename T>
auto tuple_repeat(const T& t)
{
    return tuple_repeat_ns::tuple_repeat(t, std::make_index_sequence<N>{});
}

template<size_t N, typename T>
struct computes_tuple_repeat
{
    auto operator()(const T& t) const
    {
        return tuple_repeat<N,T>(t);
    }
};

Also, here is some of the actual compiler error output:

1>[my_project]\core\thrust_wrapper.h(71): error C2971: 'thrust::tuple_element': template parameter 'N': 'i': a variable with non-static storage duration cannot be used as a non-type argument
1>c:\program files\nvidia gpu computing toolkit\cuda\v8.0\include\thrust\tuple.h(67): note: see declaration of 'thrust::tuple_element'
1>[my_project]\core\tuple_repeat.h(9): note: see declaration of 'i'
1>[my_project]\core\tuple_repeat.h(9): note: see reference to alias template instantiation 'tuple_element_t>' being compiled
with
[
T=unsigned char
]
1>[my_project]\core\tuple_repeat.h(14): note: see reference to class template instantiation 'tuple_repeat_ns::tuple_repeat_helper>' being compiled
with
[
T=unsigned char,
_Ty=::size_t
]
1>[my_project]\core\tuple_repeat.h(32): note: see reference to class template instantiation 'tuple_repeat_ns::tuple_repeat_traits' being compiled
with
[
T=unsigned char
]
1>[my_project]\core\types.h(39): note: see reference to alias template instantiation 'tuple_repeat_t' being compiled
1>[my_project]\core\thrust_wrapper.h(71): fatal error C1903: unable to recover from previous error(s); stopping compilation

Thank you for the help!

Update: it appears that replacing the line in tuple_repeat_helper that reads

using type = tuple<tuple_element_t<I-I, tuple<T>>...>;

with the line

using type = tuple<typename thrust::tuple_element<I-I,tuple<T>>::type...>;

averts the compiler error. This seems to solve the question of how to fix the problem, but why the error occurred to begin with is still a mystery to me. I essentially just substituted the definition of the alias instead of just using the alias... and that fixed it?

I will probably try to put together a more proper verifiable example later and possibly submit a bug report.

0 Answers
Related