c++ templates c++11 template-aliases

c++ - ¿Puedo usar alias de plantilla como parámetros de plantilla de plantilla?



c++ using (2)

¿Puedo usar alias de plantilla como parámetros de plantilla de plantilla?

template <template <typename...> class> struct foo {}; template <typename T> using simple_ptr = std::unique_ptr<T>; foo<std::unique_ptr> a; // this doesn''t work, std::unique_ptr has two parameters foo<simple_ptr> b; // does this work?


Las personas que leen la pregunta original pueden estar escribiendo estructuras que usan parámetros de plantilla de plantilla como metafunciones , como se demuestra en el siguiente listado.

template <int T> struct integer { using value = T; }; template <class T, class U, template <class...> class Function> struct binary_op { // Works for add_1, but not add_2 using type = typename Function<T, U>::type; // Works for add_2, but not add_1 using type = Function<T, U>; }; template <class T, class U> struct add_1; template <int T, int U> struct add_1<integer<T>, integer<U>> { using type = integer<T + U>; }; template <class T, class U> using add_2 = typename add_1<T, U>::type;

add_1 y add_2 son ambas meta-funciones , vamos a distinguir

  • add_1 como un ejemplo de metafunción tipo typedef anidada (compatible con c ++ 03)
  • add_2 como un ejemplo de metafunción de estilo de alias de plantilla (que requiere c ++ 11)

La estructura binary_op puede funcionar con estilo de alias de plantilla o con metafunciones de tipo typedef anidadas , pero no con ambas. En esta respuesta, muestro cómo se puede reescribir ese código TMP para evitar este problema.

Suponga que desea aplicar un parámetro de plantilla de plantilla a un paquete de parámetros de parámetros Ts... Para aplicar la metafunción, necesita cualquiera

using type = Function<Ts...>; // template-alias style

o

using type = typename Function<Ts...>::type; // nested typedef style

Sería útil disponer de otra metafunción genérica que detecte el tipo de metafunción que se aprobó y la aplique en consecuencia.

La función is_alias_metafunction , que se implementa a continuación, es un bloque de construcción para dicha instalación:

#include <type_traits> template <class... Ts> struct sequence; template <class T> struct check { static constexpr bool value = true; }; template < template <class...> class Function, class S, class Check = void > struct is_alias_metafunction { static constexpr bool value = true; }; template < template <class...> class Function, class... Ts > struct is_alias_metafunction< Function, sequence<Ts...>, typename std::enable_if< check<typename Function<Ts...>::type>::value >::type > { static constexpr bool value = false; };

Ahora, podemos escribir una apply metafunción que aplique un parámetro de plantilla de plantilla al paquete de parámetros Ts... , independientemente de si Function es un alias de plantilla o una estructura de plantilla.

template < bool IsAlias, template <class...> class Function, class S > struct apply_impl; template <template <class...> class Function, class... Ts> struct apply_impl<true, Function, sequence<Ts...>> { using type = Function<Ts...>; }; template <template <class...> class Function, class... Ts> struct apply_impl<false, Function, sequence<Ts...>> { using type = typename Function<Ts...>::type; }; template <template <class...> class Function, class... Ts> using apply = typename apply_impl< is_alias_metafunction<Function, sequence<Ts...>>::value, Function, sequence<Ts...> >::type;

Ahora podemos usar la metafunción de apply siguiente manera:

using type = apply<Function, Ts...>;

y abstraerá la diferencia entre las metafunciones ''heredadas'' y las metafunciones modernas (c ++ 11).


Sí, aparentemente está permitido. De acuerdo con el último borrador del próximo estándar que pude encontrar, se afirma que

Una plantilla-argumento para una plantilla plantilla-parámetro será el nombre de una plantilla de clase o una plantilla de alias [...].

Sin embargo, las plantillas de alias casi nunca se admiten en este momento, por lo que es posible que tenga problemas para hacerlo funcionar con la mayoría de los compiladores.