template
le funzioni non sono funzioni e std::endl
è una funzione template
.
Non è possibile passare una funzione template
in giro. Tuttavia, è possibile passare un oggetto funzione che rappresenta un sovraccarico attorno.Scrivi tale funtore è piuttosto semplice:
struct endl_overloadset {
template<typename... Args>
auto operator()(Args&&...args)const
->decltype(std::endl(std::forward<Args>(args)))
{ return (std::endl(std::forward<Args>(args))) };
template<typename T,typename=typename std::enable_if<\
std::is_same< decltype(static_cast<T>(std::endl)), T >::value\
>::type>\
operator T() const { return std::endl; }
};
ma trovo che, per essere un po 'troppo come boilerplate, quindi scrivere alcune macro che fanno il lavoro per voi:
#define RETURNS(X) ->decltype(X) { return (X); } // C++11 lacks non-lambda return value deduction
#define OVERLOAD_SET(F) struct {\
template<typename... Args>\
auto operator()(Args&&...args)const\
RETURNS(F(std::forward<Args>(args)...))\
template<typename T,typename=typename std::enable_if<\
std::is_same< decltype(static_cast<T>(F)), T >::value\
>::type>\
operator T() const { return F; }\
}
static OVERLOAD_SET(std::endl) Endl;
poi passare Endl
al numero f
e chiamando il numero Endl(Blah)
termina facendo std::endl(Blah)
. Allo stesso modo, assegnare Endl
a una variabile o passarlo a un metodo equivale sostanzialmente all'assegnazione di una variabile a std::endl
oa un metodo (risoluzione di overload).
Purtroppo, il OVERLOAD_SET
non può essere utilizzato all'interno di una funzione, in quanto i tipi locali non possono avere metodi template
. Se può essere utilizzato all'interno di una funzione, quindi:
f(1,2,3, OVERLOAD_SET(std::endl)());
farebbe quello che volevi. Ma quella sarebbe la lingua che vuoi programmare, non la lingua che hai. (Ancora meglio sarebbe la proposta di @ Xeo di permettere che i functor del set di overload vengano generati automaticamente usando qualche ulteriore abuso casuale della sintassi []
, piuttosto che fare affidamento sui macro).
Live example, dove passo il mio endl_functor
ad un print
metodo e quindi utilizzare <<
su di esso senza ulteriori indugi.
Quindi non c'è modo di scrivere qualcosa che permetta all'utente di usare i modificatori con i loro nomi regolari, invece di cose come narrow_endl? – user697683
@ user697683 se vuoi scrivere una funzione di stampa avvolgendo un ostream, puoi anche introdurre la funzionalità di wrapping per la formattazione (cioè non permettere di utilizzare i manipolatori ostream nell'interfaccia e fornire alternative). Ma poi si finirebbe con un printf implementato su ostream che è molto probabilmente implementato su C printf. – rubenvb