Digamos que tienes alguna clase de objetivo con alguno de sus métodos:valor de retorno vacío de una función que se utiliza como entrada para una función con plantilla es visto como un parámetro
class Subject
{
public:
void voidReturn() { std::cout<<__FUNCTION__<<std::endl; }
int intReturn() { std::cout<<__FUNCTION__<<std::endl; return 137; }
};
y una clase de valor (similar en concepto a Boost .Any):
struct Value
{
Value() {}
Value(Value const & orig) {}
template< typename T > Value(T const & val) {}
};
Y quiero producir un objeto de valor usando un método de la clase Asunto:
Subject subject;
Value intval(subject.intReturn());
Value voidVal(subject.voidReturn()); // compilation error
obtengo los siguientes errores en VC++ 2008:
error C2664: 'Value::Value(const Value &)' : cannot convert parameter 1 from 'void' to 'const Value &'
Expressions of type void cannot be converted to other types
y gcc 4.4.3:
/c/sandbox/dev/play/voidreturn/vr.cpp:67: error: invalid use of void expression
El contexto de esto es cuando usted quiere usarlo dentro de una clase de plantilla:
template< typename Host, typename Signature > class Method;
// Specialization for signatures with no parameters
template< typename Host, typename Return >
class Method< Host, Return() >
{
public:
typedef Return (Host::*MethodType)();
Method(Host * host, MethodType method) : m_Host(host), m_Method(method) {}
Value operator()() { return Value((m_Host->*m_Method)()); }
private:
Host * m_Host;
MethodType m_Method;
};
el uso de esta clase método del método que devuelve algo (es decir, intReturn) se vería así:
Method< Subject, int() > intMeth(&subject, &Subject::intReturn);
Value intValue = intMeth();
Sin embargo, hacer esto con el método voidReturn:
Method< Subject, void() > voidMeth(&subject, &Subject::voidReturn);
Value voidValue = voidMeth();
produce errores similares como anteriormente.
Una solución es especializarse aún parcialmente Método para este tipo de retorno void:
template< typename Host >
class Method< Host, void() >
{
public:
typedef void Return;
typedef Return (Host::*MethodType)();
Method(Host * host, MethodType method) : m_Host(host), m_Method(method) {}
Value operator()() { return (m_Host->*m_Method)(), Value(); }
private:
Host * m_Host;
MethodType m_Method;
};
Además de que sólo sentirse fea, yo también estoy queriendo especializar la clase Método para los números X de los parámetros de la firma, que ya implica una gran cantidad de duplicación de código (con suerte Boost.Preprocessor puede ayudar aquí), y luego agregar una especialización para los tipos de devolución vacía simplemente duplica ese esfuerzo de duplicación.
¿Hay alguna forma de evitar esta segunda especialización para los tipos de devolución de vacío?
+1. Esta es una pregunta muy bien escrita, creo. –
Absolutamente. En segundo lugar que – Chubsdad