Pregunta

Estoy escribiendo un código de puntos simple mientras pruebo Visual Studio 10 (Beta 2), y encontré este código donde esperaría que SFINAE se activara, pero parece que no:

template<typename T>
struct point {
    T x, y;
    point(T x, T y) : x(x), y(y) {}
};

template<typename T, typename U>
struct op_div {
    typedef decltype(T() / U()) type;
};

template<typename T, typename U>
point<typename op_div<T, U>::type>
operator/(point<T> const& l, point<U> const& r) {
    return point<typename op_div<T, U>::type>(l.x / r.x, l.y / r.y);
}

template<typename T, typename U>
point<typename op_div<T, U>::type>
operator/(point<T> const& l, U const& r) {
    return point<typename op_div<T, U>::type>(l.x / r, l.y / r);
}

int main() {
    point<int>(0, 1) / point<float>(2, 3);
}

Esto da error C2512: 'point<T>::point' : no appropriate default constructor available

Dado que es una versión beta, hice una verificación rápida de cordura con el compilador comeau en línea y coincide con un error idéntico, por lo que parece que este comportamiento es correcto, pero no veo por qué.

En este caso, algunas soluciones consisten simplemente en alinear el decltype(T() / U()), para darle a la clase de puntos un constructor predeterminado, o para usar decltype en la expresión de resultado completa, pero recibí este error al intentar simplificar un error que estaba recibiendo con una versión de op_div que no requería un constructor predeterminado*, así que Preferiría mejorar mi comprensión de C++ en lugar de simplemente hacer lo que funciona.

¡Gracias!


*:el original:

template<typename T, typename U>
struct op_div {
    static T t(); static U u();
    typedef decltype(t() / u()) type;
};

Lo que da error C2784: 'point<op_div<T,U>::type> operator /(const point<T> &,const U &)' : could not deduce template argument for 'const point<T> &' from 'int', y también para el point<T> / point<U> sobrecarga.

¿Fue útil?

Solución

No estoy 100% seguro.Parece que el compilador necesita crear una instancia de ambas sobrecargas para determinar cuál es mejor, pero al intentar crear una instancia del otro op_div con T = int y U = point<float>, esto genera un error que no está cubierto por SFINAE (el error no es que op_div no tenga tipo en este caso, pero ese tipo no se puede determinar).

Podría intentar desactivar la segunda sobrecarga si el segundo tipo es un punto (boost::disable_if).

Además, lo que parece funcionar es la declaración de tipo de retorno pospuesta (eliminando la estructura op_div, pero dependiendo de qué características de C++ 0x son compatibles con su compilador):

template<typename T, typename U>
auto
operator/(point<T> const& l, point<U> const& r) -> point<decltype(l.x / r.x)> {
    return {l.x / r.x, l.y / r.y};
}

template<typename T, typename U>
auto
operator/(point<T> const& l, U const& r) -> point<decltype(l.x / r)> {
    return {l.x / r, l.y / r};
}

Otros consejos

Diría que su error está aquí:

template<typename T>
struct point {
    T x, y;
    point(T x, T y) : x(x), y(y) {}
};

Cambie su definición de estructura a esto:

template<typename T>
struct point<T> {
    T x, y;
    point(T x, T y) : x(x), y(y) {}
};

Si desea utilizar un tipo genérico T, debe especificarlo en la definición.

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