Pregunta

Actualmente estoy en el proceso de escribir sobrecargas del operador aritmético para tuplas. El operador itera sobre la tupla para realizar la operación en cada uno de sus elementos individuales. Aquí está la definición para el operador +=:

template< typename... Ts, std::size_t I = 0 >
inline typename std::enable_if< I == sizeof... (Ts), std::tuple< Ts... >& >::type operator +=(std::tuple< Ts... >& lhs, const std::tuple< Ts... >& rhs)
{
    return lhs;
}

template< typename... Ts, std::size_t I = 0 >
inline typename std::enable_if< I != sizeof... (Ts), std::tuple< Ts... >& >::type operator +=(std::tuple< Ts... >& lhs, const std::tuple< Ts... >& rhs)
{
    std::get< I >(lhs) += std::get< I >(rhs);
    return operator +=< Ts..., I + 1 >(lhs, rhs);
}

Desafortunadamente, cuando intento llamar al operador, GCC 4.6 no puede decidir qué sobrecarga debe usar. Por ejemplo:

std::tuple< int, int, int, int > a = std::make_tuple(1, 2, 3, 4), b = std::make_tuple(5, 6, 7, 8);
a += b;

Produce el siguiente error:

:/Workspace/raster/main.cpp:833:7:   instantiated from here
C:/Workspace/raster/main.cpp:809:45: error: no matching function for call to 'operator+=(std::tuple<int, int, int, int>&, const std::tuple<int, int, int, int>&)'
C:/Workspace/raster/main.cpp:809:45: note: candidates are:
C:/Workspace/raster/main.cpp:800:151: note: template<class ... Ts, unsigned int I> typename std::enable_if<(I == sizeof (Ts ...)), std::tuple<_TElements ...>&>::type operator+=(std::tuple<_TElements ...>&, const std::tuple<_TElements ...>&)
C:/Workspace/raster/main.cpp:806:83: note: template<class ... Ts, unsigned int I> typename std::enable_if<(I != sizeof (Ts ...)), std::tuple<_TElements ...>&>::type operator+=(std::tuple<_TElements ...>&, const std::tuple<_TElements ...>&)

Lo cual es extraño desde el std::enable_if La condición debe rechazar la llamada inapropiada. Por ahora, tengo la siguiente solución que en realidad fue mi implementación previa. La versión anterior es, de hecho, un intento de simplificación.

template< std::size_t I, typename... Ts >
inline typename std::enable_if< I == sizeof... (Ts), std::tuple< Ts... >& >::type assignadd_impl(std::tuple< Ts... >& lhs, const std::tuple< Ts... >& rhs)
{
    return lhs;
}

template< std::size_t I, typename... Ts >
inline typename std::enable_if< I != sizeof... (Ts), std::tuple< Ts... >& >::type assignadd_impl(std::tuple< Ts... >& lhs, const std::tuple< Ts... >& rhs)
{
    std::get< I >(lhs) += std::get< I >(rhs);
    return assignadd_impl< I + 1, Ts... >(lhs, rhs);
}

template< typename... Ts >
inline std::tuple< Ts... >& operator +=(std::tuple< Ts... >& lhs, const std::tuple< Ts... >& rhs)
{
    return assignadd_impl< 0, Ts... >(lhs, rhs);
}

Esto compila y funciona como se esperaba. ¿Por qué la versión simplificada se niega a compilar? Gracias.

¿Fue útil?

Solución

El uso de argumentos de plantilla especificados explícitamente en una función o plantilla de clase requiere que aparezca cualquier paquete de parámetros de plantilla al final de la lista de parámetros de plantilla general. Moviente Ts... Al final de las listas de parámetros de plantilla y cambiar las llamadas de manera adecuada hace que el código funcione. Sección 14.8.2.1 de el borrador actual de C ++ 0x Los estados que los paquetes de parámetros que no están al final de la lista de parámetros de plantilla no se pueden deducir de una llamada de función (lo que hace que su código original falle), pero especificando explícitamente todos los argumentos de plantilla a operator+= En todos los casos, todavía causa un error SFINAE. Una pregunta anterior tiene un enlace al texto exacto que lo prohíbe; Documentación de IBM Dice que también es un error.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top