我通常不写C++,今天我尝试了C++模板,我实现了一个Maybe类型,看起来像这样
#include <functional>
#include <iostream>
#include <string>
template<typename T>
class TMaybe
{
T value;
public:
TMaybe() : value(nullptr){}
TMaybe(T &&v) : value(v){}
TMaybe(T v) : value(v){}
};
template<typename T, typename R>
TMaybe<R> maybe_if(const TMaybe<T> &m, std::function<R(T v)> f){
return (m.value != nullptr) ? TMaybe<R>(f(m)) : TMaybe();
}
int main(){
int i = 10;
auto m = TMaybe<int>(i);
auto plus_ten = [](int i) -> int {return i + 10;};
maybe_if(m, plus_ten); // could not deduce template argument for 'std::function<R(T)>' from 'main::<lambda_17413d9c06b6239cbc7c7dd22adf29dd>'
}
但是错误消息could not deduce template argument for 'std::function<R(T)>' from 'main::<lambda_17413d9c06b6239cbc7c7dd22adf29dd>'
没有太大帮助,你能发现这个错误吗?
2条答案
按热度按时间icnyk63a1#
编译器只能从
f
推导出R
,如果你传递给它一个std::function<R(T)>
的实际示例;传递lambda是行不通的,因为lambda不是std::function
特殊化的示例。编写代码的正确方法是允许任何函子类型,并从中推导出
R
:56lgkhnf2#
模板参数推导发生在Lambda到
std::fucntion
的隐式转换之前。类型推导不考虑隐式转换(上面列出的类型调整除外):这是overload resolution的工作,稍后会执行。
因此编译器只能从“
f
“(函子)推导出“R
“(返回类型),如果你传递一个std::function<R(T)>
类型的实际示例。C++20示例(可能更高版本)
使用
std::type_identity_t
,例如:旧编译器示例
如果你的项目不允许C++20,你需要把函数类型作为模板参数,并从那里推导出
R
。对于MSVC 2015,请使用
std::result_of
对于MSVC 2010,请使用
decltype
MSVC 2010有
std::result_of
,但不允许函数使用默认模板参数,因此我们做了如下操作: