template
funkcje nie są funkcjami, a std::endl
jest funkcją . Nie można przekazać funkcji template
dookoła. Można jednak przekazać obiekt funkcji reprezentujący zestaw przeciążeniowy.Pisanie takiego funktora jest całkiem proste:
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; }
};
ale uważam, że jest to trochę za dużo jak boilerplate, więc napisać kilka makr, które wykona pracę za Ciebie:
#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;
następnie przekazać Endl
do twojego f
, a wywołanie Endl(Blah)
kończy się robi std::endl(Blah)
. Podobnie przypisanie Endl
do zmiennej lub przekazanie jej do metody zasadniczo powoduje to samo, co przypisanie std::endl
do zmiennej lub przekazanie jej do metody (rozdzielczość przeciążenia Wrt).
Niestety, OVERLOAD_SET
nie może być używane w ramach funkcji, ponieważ typy lokalne nie mogą mieć metod template
. Jeśli można go użyć w funkcji, to:
f(1,2,3, OVERLOAD_SET(std::endl)());
zrobi to, co chcesz. Ale to jest język, w którym chcesz programować, a nie język, który masz. (Jeszcze lepiej byłoby, gdyby propozycja @ Xeo pozwalała na automatyczne generowanie funktorów przeciążenia za pomocą losowego dalszego nadużywania składni, zamiast polegania na makrach).
Live example, gdzie mogę przekazać moje endl_functor
się do print
metodę, a następnie użyć <<
na nim bez zbędnych ceregieli.
Więc nie ma sposobu, aby napisać coś, co pozwoliłoby użytkownikowi używać modyfikatorów według ich zwykłych nazw, zamiast takich rzeczy jak narrow_endl? – user697683
@ user697683 jeśli zamierzasz napisać funkcję drukowania owijając ostream, możesz równie dobrze wprowadzić funkcje wrapper do formatowania (tj. Nie zezwalaj na używanie manipulatorów ostream w interfejsie i dostarczaj alternatyw). Ale wtedy skończyłoby się na tym, że printf został zaimplementowany na szczycie ostream, który najprawdopodobniej został zaimplementowany na szczycie C printf. – rubenvb