İş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..)>::type
ve decltype(std::declval<F>()(std::declval<Args>()...)
hepsi hakkında INVOKE
. Yazmak için biraz daha uzun olmasına ek olarak declval
/ decltype
doğrudan kullanmak , yalnızca F
doğrudan çağrılabilirse geçerlidir (bir işlev nesnesi türü veya bir işlev veya bir işlev işaretçisi). result_of
ayrıca üye işlevlerine işaretçileri ve üye verilerine işaretçileri destekler.
Başlangıçta, SFINAE dostu bir ifadeyi kullanmak declval
/ decltype
garantilemek, std::result_of
kesinti hatası yerine size sert bir hata verebilir. Bu C ++ 14'te düzeltildi: std::result_of
artı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 F
s ‡ 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_of
geç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
.
decltype
daha çirkin ama aynı zamanda daha güçlü.result_of
yalnızca çağrılabilir türler için kullanılabilir ve bağımsız değişken olarak türler gerektirir. Örneğin,result_of
burada 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 etmekF
iç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+u
result_of