Bap*_*cht 4 c++ lambda templates type-inference c++11
我有一个boost :: variant,我想只在变量属于特殊类型时才执行仿函数,所以我编写了这个函数:
template<typename T, typename Variant>
void if_init(Variant& opt_variant, std::function<void(T)> functor){
if(auto* ptr = boost::get<T>(&opt_variant)){
functor(*ptr);
}
}
Run Code Online (Sandbox Code Playgroud)
这很好用,但我希望推导出类型T,这样我就可以写出:
if_init(b, [](double var){ std::cout << "I'm double and set" << std::endl; });
Run Code Online (Sandbox Code Playgroud)
但是没有推断出类型:
type_inference.cpp:19:5: error: no matching function for call to 'if_init'
if_init(b, [](double var){ std::cout << "I'm double and set" << std::endl; });
^~~~~~~
type_inference.cpp:10:6: note: candidate template ignored: failed template argument deduction
void if_init(Variant& opt_variant, std::function<void(T)> functor){
Run Code Online (Sandbox Code Playgroud)
如果我写:
if_init<double>(b, [](double var){ std::cout << "I'm double and set" << std::endl; });
Run Code Online (Sandbox Code Playgroud)
它运作良好.
有没有办法推断出类型T?我想只输入一次T. 这里的类型很短,但在实际情况中,有很长的类型.
我正在使用CLang 3.2.
这是完整的测试用例(第一个调用编译不是第二个):
#include <iostream>
#include <functional>
#include <boost/variant.hpp>
typedef boost::variant<int, double> Test;
template<typename T, typename Variant>
void if_init(Variant& opt_variant, std::function<void(T)> functor){
if(auto* ptr = boost::get<T>(&opt_variant)){
functor(*ptr);
}
}
int main(){
Test b = 1.44;
if_init<double>(b, [](double var){ std::cout << "I'm double and set" << std::endl; });
if_init(b, [](int var){ std::cout << "I'm int and set" << std::endl; });
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我建议您将其std::function<Sig>视为任何一个符合Sig签名的仿函数的容器- 并且可以随时替换.该功能非常方便,例如std::vector<std::function<Sig>>因为这样的容器可以容纳不同类型的仿函数.
在你的情况下,因为你只关心只有一个仿函数,你真的不需要它的功能std::function<Sig>.因此,我建议您声明您的功能模板,如下所示:
template<typename T, typename Variant, typename Functor>
void if_init(Variant& opt_variant, Functor functor);
Run Code Online (Sandbox Code Playgroud)
如果你担心,这不会传达Functor必须符合void(T)签名,请注意,std::function<Sig>并没有强制执行,要么:虽然很明显,你会最终有一个编译错误,这不是一个很好的一个.计划进行更改(也许您的实现也有),但更改为其他类型的错误.对你的情况仍然没有帮助.
我个人使用模板别名(在模板参数列表中)来记录和强制仿函数应该遵循的内容.这最终看起来像:
// Documents that e.g. long l = std::forward<Functor>(functor)(42.)
// should be a valid expression -- a functor that returns int would
// also be accepted.
// Triggers a hard-error (typically a static_assert with a nice message)
// on violation.
template<typename Functor, Requires<is_callable<Functor, long(double)>>...>
R foo(Functor functor);
// Documents that this function template only participates in overload resolution
// if the functor conforms to the signature.
// Does not trigger a hard-error (necessary by design); if everything goes right
// then another overload should be picked up -- otherwise an error of the kind
// 'no matching overload found' is produced
template<typename Functor, EnableIf<is_callable<Functor, long(double)>>...>
R bar(Functor functor);
Run Code Online (Sandbox Code Playgroud)
至于您的确切问题,C++的规则不允许在您的情况下推导出模板参数.它真的不是一个容易解决的"问题",如果它是一个.您可以在此找到更多相关信息.
| 归档时间: |
|
| 查看次数: |
1560 次 |
| 最近记录: |