c++ templates type-inference inferred-type

Inferencia de tipo de parámetro de plantilla c++



templates type-inference (1)

Tengo una plantilla en C ++

template<typename T, T* P> struct Ptr {};

entonces puedo usarlo como tal:

const int i = 0; Ptr<int, &i> ptr;

o

Ptr<decltype(i), &i> ptr;

Pero no quiero especificar el tipo int o identidad i dos veces, quiero usar solo

Ptr<&i> ptr;

y deje que el compilador int parte de tipo int por sí mismo.

¿Cómo puedo declarar mi plantilla para hacer eso?

He leído esta pregunta pero la respuesta es usar macros, eso no es bueno: ¿ plantilla de plantilla c ++?

¿Puedo hacer esto solo con una plantilla sin macros? Estoy usando Visual C ++ 2013.


ACTUALIZAR

c ++ 17 introdujo " P0127R2 Declaración de parámetros de plantilla sin tipo con auto ", lo que permite declarar un parámetro o parámetros de plantilla sin tipo con auto como marcador de posición para el tipo real:

template <auto P> struct Ptr {};

Es decir, P es un parámetro de plantilla sin tipo. Su tipo se puede inferir con decltype(P) .

auto en una lista de parámetros de plantilla está sujeto a deducciones bien conocidas y reglas de orden parcial. En su caso, el tipo puede limitarse a aceptar solo punteros:

template <auto* P> struct Ptr {};

Tenga en cuenta que la sintaxis que utiliza auto es suficiente incluso para una inspección más detallada, por ejemplo:

template <typename F> struct FunctionBase; template <typename R, typename... Args> struct FunctionBase<R(*)(Args...)> {}; template <auto F> struct Function : FunctionBase<decltype(F)> {};

También es posible usar el tipo inferido como una restricción para otros parámetros de plantilla:

template <auto I, decltype(I)... Is> struct List {};

Vieja respuesta

Como está preguntando acerca de una solución basada en plantillas de clase pura sin la ayuda de definiciones de macro, la respuesta es simple: por ahora (diciembre de 2014, c ++ 14 ) no es posible .

Este problema ya ha sido identificado por el Comité Estándar WG21 C ++ como una necesidad y hay varias propuestas para permitir que las plantillas infieran automáticamente el tipo de argumentos de plantilla sin tipo.

El más cercano es N3601 Parámetros de plantilla implícitos :

Parámetros de plantilla implícitos

El propósito de este ejemplo es eliminar la necesidad de la template<typename T, T t> redundante template<typename T, T t> idioma. Este idioma es ampliamente utilizado, con más de 100k hits en Google.

El objetivo es poder reemplazar una declaración de template<typename T, T t> struct C; como template<typename T, T t> struct C; con otra declaración para que podamos instaurar la plantilla como C<&X::f> lugar de tener que decir C<decltype(&X::f), &X::f> .

La idea básica es poder decir template<using typename T, T t> struct C {/* ... */}; para indicar que T debe deducirse. Para describir con más detalle, consideramos algunos ejemplos extendidos de clases de plantilla y funciones.

[...]

La idea clave es que pasar el tipo del segundo parámetro de plantilla es información redundante porque se puede inferir usando la deducción de tipo ordinario del segundo parámetro de tipo. Con eso en mente, proponemos que anteponer un parámetro de plantilla con el uso indica que no debe pasarse explícitamente como un argumento de plantilla, sino que se deducirá de los argumentos de plantilla posteriores que no sean de tipo. Esto inmediatamente nos permite mejorar la usabilidad de describe_field siguiente manera.

template<using typename T, T t> struct describe_field { /* ... */ }; /* ... */ cout << describe_field<&A::f>::name; // OK. T is void(A::*)(int) cout << describe_field<&A::g>::arity; // OK. T is double(A::*)(size_t)

Una propuesta similar es la que se incluye en los Tidbits de plantilla N3405 :

T para dos

El ejemplo motivador es un rasgo de tipo de reflexión putativo que da propiedades de un miembro de la clase.

struct A { void f(int i); double g(size_t s); }; /* ... */ cout << describe<&A::f>::name; // Prints "f" cout << describe<&A::g>::arity; // prints 1

La pregunta es "¿cómo debería ser la declaración de descripción?" Dado que toma un parámetro de plantilla que no es de tipo, debemos especificar el tipo del parámetro utilizando el idioma familiar (100k hits en Google) “template<class T, T t>”

template<typename T, T t> struct describe;

[...]

Nuestra idea clave es que pasar el tipo del segundo parámetro de plantilla es (casi siempre) información redundante porque se puede inferir usando la deducción de tipo ordinario del segundo parámetro de tipo. Con eso en mente, proponemos permitir que describe se declare de la siguiente manera.

template<typename T t> struct describe; /* ... */ cout << describe<&A::f>::name; // OK. T is void(A::*)(int) cout << describe<&A::g>::arity; // OK. T is double(A::*)(size_t)

El estado actual de ambas propuestas se puede rastrear en el número 9 del EWG .

Hay otras discussions proponen una sintaxis alternativa con auto :

template <auto T> struct describe;