【发布时间】:2015-09-19 05:44:40
【问题描述】:
我有以下代码,用于接受 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;
}
我的问题是当我调用这个函数时编译器无法推断出 T 的类型
map(someFuncReturningQVariant(), [](const QByteArray& array) -> QString {
return array.toString();
});
编译器报错(从原来的错误中清除,类型名称较长):
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'
这是因为 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();
});
当然,这更难看。
【问题讨论】: