我有以下类(class):
class FunctionCallback
{
public:
static CallbackHandle Create(const std::function<void(void)> &function);
template<typename T,typename... TARGS>
static CallbackHandle Create(const std::function<T(TARGS...)> &function);
};
然后我这样调用“创建”:
FunctionCallback::Create<void,float>([](float f) -> void {}); // Whether I use a lambda-function or a function pointer makes no difference
即使那应该是正确的(?),visual studio 会在阅读消息时强调该行:
Error: no instance of overloaded function "FunctionCallback::Create" matches the argument list
argument types are: (lambda []void (float f)->void)
但是该程序在 visual studio 中编译正常,没有任何警告或错误。 g++-5 无法将其与类似消息一起编译。
将其更改为:
FunctionCallback::Create<void,float>(std::function<void(float)>([](float f) -> void {}));
它不再显示消息并在 windows 和 linux 上编译。
除非我明确指定,否则为什么它不能正确推断出类型?
最佳答案
你几乎从不想推断类型橡皮擦的类型,即 std::function
是一个例子。除了少数异常(exception),模板类型推导试图推断出参数的确切类型。对于 std::function<T>
-type 参数这意味着编译器可以推断出 T
如果相应的参数是 std::function
以及。 lambda 表达式的类型不是 std::function
.
即使您显式指定类型模板参数,推导仍然会在相应类型被参数替换后继续进行。在参数包的情况下,编译器仍会尝试推导其余参数,因此对于 FunctionCallback::Create<void,float>
编译器最终得到:
template <typename... TARGS>
static CallbackHandle Create(std::function<void(float, TARGS...)> function);
这不会匹配除 std::function<void(float, TARGS...)>
以外的任何内容(或从这种类型派生的东西);否则扣除TARGS
失败。
如果您的目标是始终明确指定参数包的类型,您可以将该包(或整个参数)放在非推导上下文中:
template <typename T> struct identity { using type = T; };
template <typename T> using identity_t = typename identity<T>::type;
struct FunctionCallback
{
template <typename T, typename... TARGS>
static void Create(identity_t<std::function<T(TARGS...)>> function);
};
FunctionCallback::Create<void, float>([](float f) -> void {});
然而,在这种情况下,您将不得不付出类型删除的代价。相反,您可以考虑接受任何函数对象类型:,让编译器推断出参数的确切类型:
struct FunctionCallback
{
template <typename F>
static void Create(F function){}
};
FunctionCallback::Create([](float f) -> void {});
关于c++ - 隐式模板参数无效,但仍可编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34242956/