İşlev çağrısı gibi olmayan bir şeye ihtiyacınız varsa std::result_of, bu geçerli değildir. decltype()size herhangi bir ifadenin türünü verebilir.
Kendimizi bir işlev çağrısının dönüş türünü ( std::result_of_t<F(Args...)>ve arasında decltype(std::declval<F>()(std::declval<Args>()...)) belirlemenin farklı yollarıyla sınırlarsak , o zaman bir fark vardır.
std::result_of<F(Args...) olarak tanımlanır:
İfade
INVOKE (declval<Fn>(), declval<ArgTypes>()...), değerlendirilmemiş bir işlenen olarak ele alındığında (Madde 5) iyi biçimlendirilmişse, üye typedef türü, türü decltype(INVOKE (declval<Fn>(), declval<ArgTypes>()...));
başka şekilde adlandırır, üye türü olmaz.
Arasındaki fark result_of<F(Args..)>::typeve decltype(std::declval<F>()(std::declval<Args>()...)hepsi hakkında INVOKE. Yazmak için biraz daha uzun olmasına ek olarak declval/ decltypedoğrudan kullanmak , yalnızca Fdoğrudan çağrılabilirse geçerlidir (bir işlev nesnesi türü veya bir işlev veya bir işlev işaretçisi). result_ofayrıca üye işlevlerine işaretçileri ve üye verilerine işaretçileri destekler.
Başlangıçta, SFINAE dostu bir ifadeyi kullanmak declval/ decltypegarantilemek, std::result_ofkesinti hatası yerine size sert bir hata verebilir. Bu C ++ 14'te düzeltildi: std::result_ofartık SFINAE dostu olması gerekiyor ( bu makale sayesinde ).
Dolayısıyla uyumlu bir C ++ 14 derleyicisinde, std::result_of_t<F(Args...)>kesinlikle üstündür. Daha net, daha kısa ve doğru bir şekilde † daha fazla Fs ‡ destekliyor .
† Diğer bir deyişle, üyelere işaretçilerin girmesine izin vermek istemediğiniz bir bağlamda kullanmıyorsanız
std::result_of_t, başarısız olmasını isteyebileceğiniz bir durumda başarılı olursunuz.
‡ İstisnalar dışında. Üyelere işaretçileri desteklerken, result_ofgeçersiz bir tür kimliği başlatmaya çalışırsanız çalışmayacaktır . Bunlar, bir işlevi döndüren veya değere göre soyut türleri alan bir işlevi içerir. Ör .:
template <class F, class R = result_of_t<F()>>
R call(F& f) { return f(); }
int answer() { return 42; }
call(answer); // nope
Doğru kullanım olurdu result_of_t<F&()>, ama bu hatırlamanız gerekmeyen bir ayrıntı decltype.
decltypedaha çirkin ama aynı zamanda daha güçlü.result_ofyalnızca çağrılabilir türler için kullanılabilir ve bağımsız değişken olarak türler gerektirir. Örneğin,result_ofburada kullanamazsınız :template <typename T, typename U> auto sum( T t, U u ) -> decltype( t + u );eğer argümanlar aritmetik türler olabilirse ( temsil etmekFiçin tanımlayabileceğiniz bir işlev yoktur . Kullanıcı tanımlı türler için yapabilirsiniz. Aynı şekilde (onunla gerçekten oynamadım) üye yöntemlerine çağrı yapmak bağlayıcı veya lambdas kullanmadan yapmak zor olabilirF(T,U)t+uresult_of