2015-10-14 14 views
11

binary_function è deprecato ora e verrà eliminato in C++ 17. Ho cercato su diverse pubblicazioni, ma non sono riuscito a trovare un modo esatto per sostituirlo. Mi piacerebbe sapere come dovrei scrivere il seguente codice in stile C++ 11.sostituzione per binary_function

template <class T> 
inline T absolute(const T &x) { 
    return (x >= 0) ? x : -x; 
} 

template <class T> 
struct absoluteLess : public std::binary_function<T, T, bool> { 
    bool operator()(const T &x, const T &y) const { 
     return absolute(x) < absolute(y); 
    } 
}; 

template <class T> 
struct absoluteGreater : public std::binary_function<T, T, bool> { 
    bool operator()(T &x, T &y) const { 
     return absolute(x) > absolute(y); 
    } 
}; 

EDIT: Sto utilizzando le funzioni nel seguente modo:

output[j] = *std::max_element(input.begin() + prev, input.begin() + pos, absoluteLess<float>()); 

ingresso e uscita sono vettori, all'interno di un ciclo for

+2

perché ne hai bisogno?type traits e decltype possono capire il tipo di 'operator()' senza le necessità di 'binary_function' –

+2

Come si usano queste funzioni di template? La risposta dipende dall'utilizzo. – Rostislav

+1

http://stackoverflow.com/a/22863957/642626 ecco come si trovano gli argomenti e si restituisce il tipo di qualsiasi oggetto callable. –

risposta

7

In primo luogo, il mio consiglio è quello di guardare CppCon 2015: Stephan T. Lavavej "functional: What's New, And Proper Usage". std::binary_function è menzionato sulla diapositiva 36, ​​a circa 36 minuti nel video. È possibile trovare le diapositive su github.com/CppCon/CppCon2015). Non entra nei dettagli perché non si dovrebbe usare std::binary_function, ma se si sta usando qualcosa che è stato deprecato dal C++ 11, probabilmente si trarrà vantaggio dal guardarlo.

Se si desidera che la logica attuale per non usarlo, prova a n4190:

unary_function/binary_function erano aiutanti utili quando C++ 98-era adattatori necessari argument_type/etc. typedef. Tali typedef sono non necessari dato l'inoltro perfetto, decltype di C++ 11 e così via. (E sono inapplicabili agli operatori chiamata di funzione sovraccaricata). Anche se una classe vuole fornire questi typedef per la compatibilità con le versioni precedenti di , può farlo direttamente (con un costo minore in verbosità) invece di ereditare da unary_function/binary_function, che è ciò che lo Standard stesso ha iniziato a fare quando questi helper sono stati deprecati.

Ora semplicemente non ne hai bisogno, quindi puoi rimuovere tutte le tracce dal programma.

In C++ 14 sono stati aggiunti comparatori trasparenti. Ma può essere implementato in C++ 11. Basta specializzarsi per void:

template<> 
struct absoluteLess<void> { 
    template< class T, class U> 
    constexpr auto operator()(T&& lhs, U&& rhs) const 
     -> decltype(absolute(std::forward<T>(lhs)) < absolute(std::forward<U>(rhs))) 
    { 
     return absolute(std::forward<T>(lhs)) < absolute(std::forward<U>(rhs)); 
    } 
} 
}; 

Ora il tipo può essere dedotto:

std::max_element(v.begin(), v.end(), absoluteLess<>()); 
+0

Funziona benissimo! Anche il collegamento è molto utile. – Luis

8

L'unica cosa std::binary_function fa sta fornendo la membro typedefs result_type, first_argument_type e second_argument_type. E l'unica cosa nella libreria standard che usa questi typedefs è std::not2, che è 1) sostituita rigorosamente da C++ 17 std::not_fn, 2) facilmente sostituita da un lambda in ogni caso, e 3) deprecato in C++ 17 e probabilmente andando a essere rimosso nella prossima revisione.

Se, per qualsiasi motivo, è necessario utilizzare not2, i leganti legacy (bind1st/bind2nd, sia deprecati in C++ 11 e rimossi in C++ 17), o qualche antico cosa di terze parti dopo che il protocollo , la sostituzione consiste nel definire i typedef direttamente nella classe:

using result_type = bool; 
using first_argument_type = T; 
using second_argument_type = T; 

Altrimenti, è sufficiente rimuovere l'ereditarietà.