Diciamo che avete un po 'di classe bersaglio con alcuni metodi su di esso:valore di ritorno vuoto da una funzione utilizzata come input per una funzione template è visto come un parametro di
class Subject
{
public:
void voidReturn() { std::cout<<__FUNCTION__<<std::endl; }
int intReturn() { std::cout<<__FUNCTION__<<std::endl; return 137; }
};
E una classe di valore (simile nel concetto a Boost .Any):
struct Value
{
Value() {}
Value(Value const & orig) {}
template< typename T > Value(T const & val) {}
};
E voglio produrre un oggetto di valore utilizzando un metodo dalla classe oggetto:
Subject subject;
Value intval(subject.intReturn());
Value voidVal(subject.voidReturn()); // compilation error
ottengo i seguenti errori in 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
e gcc 4.4.3:
/c/sandbox/dev/play/voidreturn/vr.cpp:67: error: invalid use of void expression
Il contesto di questo è quando si desidera utilizzarlo all'interno di una classe template:
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;
};
Utilizzando questa classe Method sul metodo che restituisce qualcosa (vale a dire intReturn) sarebbe simile:
Method< Subject, int() > intMeth(&subject, &Subject::intReturn);
Value intValue = intMeth();
Tuttavia, facendo questo con il metodo voidReturn:
Method< Subject, void() > voidMeth(&subject, &Subject::voidReturn);
Value voidValue = voidMeth();
cede errori simili come sopra.
Una soluzione è quella di specializzarsi ulteriormente parzialmente Metodo per i tipi di ritorno 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;
};
Oltre esso solo sentirsi brutta, sto anche volendo specializzarsi classe Metodo per numero X di parametri di firma, che coinvolge già un sacco di duplicazione del codice (speranzoso Boost.Preprocessor può aiutare qui), e quindi l'aggiunta di una specializzazione per i tipi di restituzione vuoti raddoppia solo lo sforzo di duplicazione.
Esiste comunque la possibilità di evitare questa seconda specializzazione per i tipi di resi void?
+1. Questa è una domanda molto ben scritta, penso. –
Assolutamente. I second that – Chubsdad