Jika Anda membutuhkan jenis sesuatu yang bukan sesuatu seperti panggilan fungsi, std::result_ofitu tidak berlaku. decltype()dapat memberi Anda jenis ekspresi apa pun.
Jika kita membatasi diri hanya pada cara yang berbeda untuk menentukan jenis kembalian dari sebuah panggilan fungsi (antara std::result_of_t<F(Args...)>dan decltype(std::declval<F>()(std::declval<Args>()...)), maka ada perbedaan.
std::result_of<F(Args...) didefinisikan sebagai:
Jika ekspresi
INVOKE (declval<Fn>(), declval<ArgTypes>()...)terbentuk dengan baik saat diperlakukan sebagai operan yang tidak dievaluasi (Klausul 5), tipe anggota typedef harus menamai tipe decltype(INVOKE (declval<Fn>(), declval<ArgTypes>()...));
jika tidak, tidak boleh ada tipe anggota.
Perbedaan antara result_of<F(Args..)>::typedan decltype(std::declval<F>()(std::declval<Args>()...)adalah tentang itu INVOKE. Menggunakan declval/ decltypesecara langsung, selain sedikit lebih lama untuk mengetik, hanya valid jika Fdapat dipanggil secara langsung (tipe objek fungsi atau fungsi atau penunjuk fungsi). result_ofSelain itu mendukung petunjuk ke fungsi anggota dan petunjuk ke data anggota.
Awalnya, menggunakan declval/ decltypemenjamin ekspresi ramah SFINAE, sedangkan std::result_ofbisa memberi Anda kesalahan keras alih-alih kegagalan deduksi. Itu telah diperbaiki di C ++ 14: std::result_ofsekarang harus ramah SFINAE (terima kasih untuk makalah ini ).
Jadi pada kompiler C ++ 14 yang sesuai, std::result_of_t<F(Args...)>sangat unggul. Ini jelas, lebih pendek, dan benar † mendukung lebih Fs ‡ .
† Kecuali, jika Anda menggunakannya dalam konteks di mana Anda tidak ingin mengizinkan petunjuk untuk anggota, jadi
std::result_of_takan berhasil dalam kasus di mana Anda mungkin ingin gagal.
‡ Dengan pengecualian. Meskipun mendukung pointer ke anggota, result_oftidak akan berfungsi jika Anda mencoba membuat id jenis yang tidak valid . Ini akan mencakup fungsi yang mengembalikan fungsi atau mengambil tipe abstrak berdasarkan nilai. Ex.:
template <class F, class R = result_of_t<F()>>
R call(F& f) { return f(); }
int answer() { return 42; }
call(answer); // nope
Penggunaan yang benar akan dilakukan result_of_t<F&()>, tetapi itu adalah detail yang tidak perlu Anda ingat decltype.
decltypelebih buruk tetapi juga lebih kuat.result_ofhanya dapat digunakan untuk tipe yang dapat dipanggil dan membutuhkan tipe sebagai argumen. Misalnya, Anda tidak dapat menggunakan diresult_ofsini:template <typename T, typename U> auto sum( T t, U u ) -> decltype( t + u );jika argumen dapat berupa tipe aritmatika (tidak ada fungsiFyang dapat Anda definisikanF(T,U)untuk mewakilit+u. Untuk tipe yang ditentukan pengguna, Anda bisa. Dengan cara yang sama (saya belum benar-benar bermain dengannya) saya bayangkan bahwa panggilan ke metode anggota mungkin sulit dilakukanresult_oftanpa menggunakan pengikat atau lambda