c++ - El argumento predeterminado de la plantilla pierde su tipo de referencia
templates template-deduction (2)
Para
foo<int>(a)
,
ARG_T
se deduce de
a
, y no se toma del argumento de plantilla predeterminado.
Como es un parámetro de función por valor y
a
es una expresión de tipo
int
, se deduce como
int
.
En general, los argumentos de plantilla predeterminados no se usan cuando la deducción de argumentos de plantilla puede descubrir cuál es el argumento.
Pero podemos forzar el uso del argumento predeterminado introduciendo un contexto no deducido para el parámetro de función. Por ejemplo:
template <class T, class ARG_T = T&>
T foo(std::enable_if_t<true, ARG_T> v1){
//...
}
O la utilidad C ++ 20
type_identity
, como lo demuestra la otra respuesta.
Considerar
#include <iostream>
#include <type_traits>
template <class T, class ARG_T = T&>
T foo(ARG_T v){
return std::is_reference<decltype(v)>::value;
}
int main() {
int a = 1;
std::cout << foo<int>(a) << ''/n'';
std::cout << foo<int, int&>(a) << ''/n'';
}
Esperaría que la salida sea 1 en ambos casos.
Pero en el primer caso es 0: coherente con la
class ARG_T = T
predeterminada
class ARG_T = T
lugar de la
class ARG_T = T&
.
¿Qué me estoy perdiendo?
ARG_T
detener
la deducción de argumentos de plantilla
para
ARG_T
del argumento de función
v
, (con la ayuda de
std::type_identity
, que podría usarse para excluir argumentos específicos de la deducción);
De lo contrario, no se utilizará el argumento de plantilla predeterminado.
p.ej
template <class T, class ARG_T = T&>
T foo(std::type_identity_t<ARG_T> v){
return std::is_reference<decltype(v)>::value;
}
Por cierto: si su compilador no admite
std::type_identity
(desde C ++ 20), puede hacer el suyo.
template<typename T> struct type_identity { typedef T type; };
template< class T >
using type_identity_t = typename type_identity<T>::type;