我有下面的代碼,是爲了接受一個Qt的QVariant並申請函子,如果變體包含一個值:推導模板參數
template<typename T, typename Functor>
inline QVariant map(const QVariant& v, Functor f)
{
return v.isValid()
? QVariant{f(qvariant_cast<T>(v))}
: v;
}
我的問題是,編譯器不能推斷出
error: no matching function for call to `map(QVariant, <lambda(const QByteArray&)>)`
note: candidate is:
template<class T, class Functor> QVariant map(const QVariant&, Functor).
note: template argument deduction/substitution failed:
couldn't deduce template parameter 'T'
:當調用該函數作爲
map(someFuncReturningQVariant(), [](const QByteArray& array) -> QString {
return array.toString();
});
編譯器會抱怨的T型(從原來的誤差,其具有較長的類型名稱清理)
這是因爲QVariant會在運行時擦除它包含的對象的類型。 (它仍然在內部知道它,很像boost::any
,而qvariant_cast<T>()
獲取原始對象)。
如何捕獲傳遞給Functor
的變量的類型並在其他地方使用它?另外,如何指定Functor
需要T
類型的參數? (我懷疑這實際上是同一個問題,或者說他們至少有相同的答案。)
請注意,我的辦法正常工作與std::optional
,因爲類型也不會被刪除:
using std::experimental::optional;
template<typename T, typename Functor>
inline auto map(const optional<T>& v, Functor f) -> optional<decltype(f(*v))>
{
return v ? optional<decltype(f(*v))>{f(*v)}
: v;
}
還要注意如果我手動指定類型,則QVariant代碼可以正常工作:
map<QByteArray>(someFuncReturningQVariant(), [](const QByteArray& array) -> QString {
return array.toString();
});
但是,當然,這很醜陋。
你有C++ 14嗎? – Yakk
@Yakk,如果我能用C++ 11脫身,我會用它,但在學術上,是的。 – thirtythreeforty