tipos sirven que plantillas para multiples los c++ templates c++11 c++14 type-promotion

sirven - plantillas multiples c++



¿Por qué mi función de plantilla no promueve ''int'' a ''T'', donde ''T''=''doble''? (3)

Tengo una clase de plantilla con el typename T Contiene una función,

template <typename T, size_t a> myClass<T,a> operator+(myClass<T,a> lhs, const T& rhs) { return lhs += rhs; } myClass<T,a> myClass<T,a>::operator+=(const T& rhs) { // Do addition, depends on ''a''. return *this; }

Cuando lo llamo con, por ejemplo,

myClass<double, 2> myObj_double_2(constructor args); myObj_double_2 = myObj_double_2 + 5.2;

Yo no tengo ningún problema.

Si sin embargo llamo

myObj_double_2 = myObj_double_2 + 5;

Entonces el compilador me da un mensaje como: No match for ''operator+'' (operand types are ''myClass<double, 2ul>'' and ''int''). Candidates are ... note: deduced conflicting types for parameter ''const T'' (''double'' and ''int'') No match for ''operator+'' (operand types are ''myClass<double, 2ul>'' and ''int''). Candidates are ... note: deduced conflicting types for parameter ''const T'' (''double'' and ''int'') .

¿Puedo escribir el código de alguna manera para permitir que se pasen tipos adicionales que tienen una conversión a T (dado que, por ejemplo, double (5) es una llamada de constructor válida)?


Cuando está utilizando la deducción de argumento de plantilla, todas las deducciones para un parámetro de plantilla deben tener el mismo resultado.

En su caso, las dos deducciones para T producen double e int , que no son las mismas, por lo que la deducción falla.

Lo que puede hacer es usar solo un argumento de función para la deducción de argumentos de plantilla y hacer que el otro no aparezca :

template <typename T, std::size_t A> void foo(myClass<T, A> arg1, typename std::common_type<T>::type arg2); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Tenga en cuenta que el tipo std::common_type<T>::type es esencialmente solo T , pero como el tipo de arg2 ahora es un tipo dependiente (su nombre aparece a la derecha de un :: , no se deduce. Por lo tanto, solo el primer argumento toma parte en la deducción y produce T = double sin ambigüedad, y luego el segundo parámetro de función solo tiene el tipo double , y tienen lugar las conversiones habituales.

Como regla general, la deducción de los argumentos de la plantilla no se cruza :: .


El compilador en la resolución de sobrecarga no encuentra un candidato adecuado para el operator+ porque T ya está siendo deducido al double y el literal 5 es un entero. Solución:

template <typename T1, typename T2, size_t a> myClass<T1,a> operator+(myClass<T1,a> lhs, const T2& rhs) { return lhs += T1(rhs); }


Te encuentras con problemas con la deducción de tipo de plantilla.

A ambos argumentos se les otorga una "posición igual" cuando se deduce el valor de T , y en este caso los dos argumentos no están de acuerdo: uno dice que T debería ser int , el otro dice que T debería ser double .

La forma correcta de solucionar esto es con los operadores de Koenig.

Haz += y + y los friend similares de tu clase e implementa en línea:

template<class T, size_t a> class myClass { // etc public: friend myClass operator+(myClass lhs, const T& rhs) { lhs += rhs; return std::move(lhs); } friend myClass& operator+=(myClass& lhs, const T& rhs) { // do addition, depends on `a` return *this; } };

Esta técnica hace algo extraño. Crea operadores sin template basados ​​en el tipo de plantilla de la clase. Estos se encuentran a través de ADL (búsqueda Koenig) cuando invoca + o += .

Obtiene uno de estos operadores por instanciación de plantilla, pero no son operadores de plantilla, por lo que no se deduce const T& y se realiza la conversión como se esperaba.