Odd compiler behaviour
Clang++
I'm getting warnings for non-deducible template arguments from Clang++, but the program outputs correctly.
Visual C++ v140
The type is detected correctly. However I get the following warning:
warning C4552: '<<': operator has no effect; expected operator with side-effect
The program does not output anything.
G++
Everything works properly.
Source code
This is basically a non-recursive std::tuple_element
implementation.
Note: To make this non-recursive, you must replace std::make_index_sequence
with a non-recursive implementation. I left it with std::make_index_sequence
in order to provide a MVCE.
deduct<std::size_t, T>
has a specialization of deduct_impl<T>
that is generated from the index sequence template argument it receives. It is used in order to deduce the type at index
in a variadic type template or tuple.
itp<std::size_t>
and itp<std::size_t, T>
is an index-type-pair used to expand the variadic indices template with a type variadic template in order to match the generated specialization.
deducer<std::size_t, T...>
puts it all together by specializing deduct<std::size_t, T>
and deduct_impl<T>
by using std::conditional_t
to generate the correct specialization.
Basically, for std::tuple<void, int, char>
, in order to get the type at index 1, it creates itp_base<0>, itp<1, int>, itp_base<2>
and passes it to deduct
and deduct_impl
.
#include <iostream>
#include <string>
#include <tuple>
template <std::size_t index>
struct itp_base {};
template <std::size_t index, typename T>
struct itp : itp_base<index> {};
template <std::size_t index, typename IndexSequence>
struct deduct;
template <std::size_t index, std::size_t... indices>
struct deduct<index, std::index_sequence<indices...>>
{
template <typename Tuple>
struct deduct_impl;
template <typename T, typename... R>
struct deduct_impl<std::tuple<itp_base<indices>..., itp<index, T>, R...>>
{
using type = T;
};
};
template <std::size_t index, typename... Types>
class deducer
{
private:
static_assert( index < sizeof...( Types ), "deducer::index out of bounds" );
template <typename IndexSequence>
struct deducer_impl;
template <std::size_t... indices>
struct deducer_impl<std::index_sequence<indices...>>
{
using type = typename deduct<index, std::make_index_sequence<index>
>::template deduct_impl
<
std::tuple
<
std::conditional_t
<
std::is_base_of<itp_base<indices>, itp<index, Types>>::value,
itp<index, Types>,
itp_base<indices>
>...
>
>::type;
};
public:
using type = typename deducer_impl<
std::make_index_sequence<sizeof...( Types )>>::type;
};
template <std::size_t index, typename... Types>
using tuple_element_t = typename deducer<index, Types...>::type;
int main()
{
tuple_element_t<3, int, void, char, std::string> s{ "string" };
std::cout << s << '\n';
}
Aucun commentaire:
Enregistrer un commentaire