我发现了std::function
和类型推导的以下行为,这对我来说是意想不到的:
#include <functional>
template <typename T>
void stdfunc_test(std::function<T(T)> func) {};
int test_func(int arg)
{
return arg + 2;
}
int main()
{
stdfunc_test([](int _) {return _ + 2;});
stdfunc_test(test_func);
}
main
中的两行都会导致错误:
没有函数模板“stdfunc_test”的实例与参数列表匹配
尝试在Visual Studio 2015中编译时。
为什么类型演绎不从函数类型中演绎模板类型,有没有变通方法?
在模板参数推导期间不执行隐式转换,除了:temp.deduct.call
通常,演绎过程会尝试查找模板参数值,这些值将使推导的 A 与 A 相同(在如上所述转换类型 A 之后)。但是,有三种情况允许差异:
但是,如果模板参数不参与模板实参推导,则进行隐式转换:(temp.arg.explicit)
如果参数类型不包含参与模板参数推导的模板参数,则将对函数参数执行隐式转换(子句[conv]),以将其转换为相应函数参数的类型。【注意:模板参数如果被明确指定,则不参与模板实参推演。
因此,如果您显式指定模板参数,它应该可以工作:
stdfunc_test<int>([](int _) {return _ + 2;});
stdfunc_test<int>(test_func);
您可以使用模板来推断函数和仿函数的签名:
#include<functional>
template<class T>
struct AsFunction
: public AsFunction<decltype(&T::operator())>
{};
template<class ReturnType, class... Args>
struct AsFunction<ReturnType(Args...)> {
using type = std::function<ReturnType(Args...)>;
};
template<class ReturnType, class... Args>
struct AsFunction<ReturnType(*)(Args...)> {
using type = std::function<ReturnType(Args...)>;
};
template<class Class, class ReturnType, class... Args>
struct AsFunction<ReturnType(Class::*)(Args...) const> {
using type = std::function<ReturnType(Args...)>;
};
template<class F>
auto toFunction( F f ) -> typename AsFunction<F>::type {
return {f};
}
template <typename T>
void stdfunc_test(std::function<T(T)> func) {};
int test_func(int arg)
{
return arg + 2;
}
int main()
{
stdfunc_test( toFunction([](int _) {return _ + 2;}) );
stdfunc_test( toFunction(test_func) );
return 0;
}
您可以在这里尝试:http://fiddle.jyt.io/github/d4ab355eb2ab7fc4cc0a48da261f0127
多亏了C11,我们收到了系列的仿函数包装器。不幸的是,我一直只听到关于这些新添加的不好的消息。最受欢迎的是它们非常慢。我测试了它,与模板相比,它们真的很糟糕。 111毫秒对1241毫秒。我认为这是因为模板可以很好地内联,而通过虚拟调用覆盖内部。 显然,在我看来,模板也有其问题: 它们必须以头的形式提供,这不是您在以封闭代码形式发布库时可能不希望做的事情, 因此,我可以假设s可以用作传递函子的事实标
如果我没有理解错的话,类模板定义了一个函数,所以当我调用时,编译器有可能进行隐式强制转换,但是在函数模板的情况下,此时没有函数定义,所以隐式强制转换不会发生。 但我不明白为什么编译器不能创建函数定义,然后应用隐式强制转换? 错误是: 在函数“int main()”中: 25:24:错误:调用“test2::add(void(&)(int))”没有匹配函数 25:24:注:候选人是:
使用以下代码生成时 生成以下诊断(代码后): 诊断: 有趣的部分不是关于歧义错误本身(这不是这里主要关注的问题)。有趣的是,当仅使用函数名调用fun时,第一个fun的模板参数F被解析为纯函数类型double(double),而第二个fun的模板参数F被解析为更期望的函数指针类型。 然而,当我们将调用<代码>乐趣(测试) 更改为<代码>乐趣( 这种行为似乎是所有Clang和GCC(以及Visual
我试图编写一个通用的obj工厂,使用可变模板调用各种类的构造函数。代码如下: 在大多数例子中,变量arg总是这样写“Args” 错误:没有可行的转换从'__bind( 在移除“ 但我不知道为什么?
我有一个模板类和一个模板返回类型的函数: 假设我想为一个特定类型扩展返回的,并专门为该类型使用函数。因此,让我们创建一个模板来保存返回类型,并在中使用它: 并用它来提供专业化: 然而,gcc和clang都拒绝了最终声明。例如,clang返回: 错误:没有与函数模板专门化“build_wrapped”匹配的函数模板 注意:已忽略候选模板:无法推断模板参数“t” 通过为创建一个明确的专门化,我可以使用