[Bug c++/108414] template meta programming

redi at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Mon Jan 16 09:35:31 GMT 2023


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108414

--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Reduced:

using size_t = decltype(sizeof(0));
template<typename T> struct type_identity { using type = T; };
template<typename T, typename U> constexpr bool is_same_v = false;
template<typename T> constexpr bool is_same_v<T, T> = true;

template<typename... Ts>
struct type_list {};

template <size_t I, typename T>
struct indexed { using type = T; };

template <size_t I, typename ...Ts>
struct indexer;

template <size_t I, typename T, typename ...Ts>
struct indexer<I, T, Ts...> : indexed<I, T>, indexer<I+1, Ts...> {};

template <size_t I, typename T>
struct indexer<I, T> : indexed<I, T> {};

template <size_t I, typename ...Ts>
using nth_element_t = typename decltype([]<typename T>(const indexed<I,
T>&){return type_identity<T>{};}(indexer<0, Ts...>{}))::type;

template<size_t I, typename T>
struct nth_type;

template<size_t I, typename ... Ts>
struct nth_type< I, type_list<Ts...> >
{
#ifndef USING
  typedef nth_element_t<I, Ts...> type; // Incorrect result with it
#else
  using type = nth_element_t<I, Ts...>; // Compile error
#endif
};

template<size_t I, typename T>
using nth_type_t = typename nth_type<I, T>::type;

using list = type_list<int, float, double>;

using elm0 = nth_type_t<0, list>;
using elm1 = nth_type_t<1, list>;
using elm2 = nth_type_t<2, list>;

static_assert( is_same_v<elm0, int> );
static_assert( is_same_v<elm1, float> );
static_assert( is_same_v<elm2, double> );


Without -DUSING

nth.cc:47:16: error: static assertion failed
   47 | static_assert( is_same_v<elm1, float> );
      |                ^~~~~~~~~~~~~~~~~~~~~~
nth.cc:48:16: error: static assertion failed
   48 | static_assert( is_same_v<elm2, double> );
      |                ^~~~~~~~~~~~~~~~~~~~~~~


With -DUSING

nth.cc: In substitution of 'template<long unsigned int I, class T> using
nth_type_t = typename nth_type::type [with long unsigned int I = 0; T =
type_list<int, float, double>]':
nth.cc:42:32:   required from here
nth.cc:38:7: error: no type named 'type' in 'struct nth_type<0, type_list<int,
float, double> >'
   38 | using nth_type_t = typename nth_type<I, T>::type;
      |       ^~~~~~~~~~
nth.cc: In substitution of 'template<long unsigned int I, class T> using
nth_type_t = typename nth_type::type [with long unsigned int I = 1; T =
type_list<int, float, double>]':
nth.cc:43:32:   required from here
nth.cc:38:7: error: no type named 'type' in 'struct nth_type<1, type_list<int,
float, double> >'
nth.cc: In substitution of 'template<long unsigned int I, class T> using
nth_type_t = typename nth_type::type [with long unsigned int I = 2; T =
type_list<int, float, double>]':
nth.cc:44:32:   required from here
nth.cc:38:7: error: no type named 'type' in 'struct nth_type<2, type_list<int,
float, double> >'
nth.cc:46:26: error: 'elm0' was not declared in this scope
   46 | static_assert( is_same_v<elm0, int> );
      |                          ^~~~
nth.cc:46:16: error: template argument 1 is invalid
   46 | static_assert( is_same_v<elm0, int> );
      |                ^~~~~~~~~~~~~~~~~~~~
nth.cc:47:26: error: 'elm1' was not declared in this scope
   47 | static_assert( is_same_v<elm1, float> );
      |                          ^~~~
nth.cc:47:16: error: template argument 1 is invalid
   47 | static_assert( is_same_v<elm1, float> );
      |                ^~~~~~~~~~~~~~~~~~~~~~
nth.cc:48:26: error: 'elm2' was not declared in this scope
   48 | static_assert( is_same_v<elm2, double> );
      |                          ^~~~
nth.cc:48:16: error: template argument 1 is invalid
   48 | static_assert( is_same_v<elm2, double> );
      |                ^~~~~~~~~~~~~~~~~~~~~~~


More information about the Gcc-bugs mailing list