Pregunta

Al tratar de responder a esta pregunta quería sugerir el uso de enable_if + disable_if para permitir la sobrecarga de un método basado en el hecho de que un tipo era (o no) polimórfico.

Así que creó un pequeño archivo de prueba:

template <class T>
void* address_of(T* p,
                 boost::enable_if< boost::is_polymorphic<T> >* dummy = 0)
{ return dynamic_cast<void*>(p); }

template <class T>
void* address_of(T* p,
                 boost::disable_if< boost::is_polymorphic<T> >* dummy = 0)
{ return static_cast<void*>(p); }

struct N { int x; };


int main(int argc, char* argv[])
{
  N n;
  std::cout << address_of(&n) << std::endl;
  return 0;
}

que parece bastante a dominar.

Sin embargo gcc (3,4 ...) ahogarse con esto:

  

test.cpp: En int main(int, char**) función:
  test.cpp: 29: error: Llamada de address_of(N*) sobrecargado es ambigua
  test.cpp: 17: nota: los candidatos son: void* address_of(T*, boost::enable_if<boost::is_polymorphic<T>, void>*) [con T = N]
  test.cpp: 20: nota: void* address_of(T*, boost::disable_if<boost::is_polymorphic<T>, void>*) [con T = N]

Parece bastante claro a la mente humana que la sobrecarga se debe utilizar aquí. Es decir, parece claro que he definido una alternativa y sólo una función se puede utilizar a la vez ... y yo habría pensado que SFINAE se haría cargo de invalidar la sobrecarga innecesaria.

Me parcheado la conexión utilizando ... (puntos suspensivos) en lugar de disable_if y requiriendo un segundo argumento ficticio ... pero sigo interesado en saber por qué el estrangulador compilador en esto.

¿Fue útil?

Solución

El compilador ahogada porque se le olvidó la ::type se arrastra en enable_if y disable_if. Las plantillas siempre se definen; es sólo que la type miembro está presente si y sólo si la expresión es true (por enable_if) o false (por disable_if).

template <class T>
void* address_of(T* p,
                 typename boost::enable_if< boost::is_polymorphic<T> >::type* dummy = 0)
{ return dynamic_cast<void*>(p); }

template <class T>
void* address_of(T* p,
                 typename boost::disable_if< boost::is_polymorphic<T> >::type* dummy = 0)
{ return static_cast<void*>(p); }

Sin la ::type de salida, las plantillas de función basta con crear sobrecargas que toman punteros a instancias de enable_if o disable_if como el segundo parámetro. Con la ::type de salida, las plantillas o bien crean una sobrecarga con un segundo parámetro de tipo void*, o se elimine la sobrecarga (es decir, el comportamiento deseado).

Otros consejos

El uso de la versión "tipo de retorno" de enable_if trabaja en 3.4.4: gcc version 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_polymorphic.hpp>
#include <iostream>

template <class T>
typename boost::enable_if< boost::is_polymorphic<T>, void* >::type
address_of(T* p)
{ return dynamic_cast<void*>(p); }

template <class T>
typename boost::disable_if< boost::is_polymorphic<T>, void* >::type
address_of(T* p)
{ return static_cast<void*>(p); }

struct N { int x; };


int main(int argc, char* argv[])
{
  N n;
  std::cout << address_of(&n) << std::endl;
  return 0;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top