c++ - 隐式模板参数无效,但仍可编译

标签 c++ templates c++11 variadic-templates implicit-conversion

我有以下类(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 {});

DEMO

然而,在这种情况下,您将不得不付出类型删除的代价。相反,您可以考虑接受任何函数对象类型:,让编译器推断出参数的确切类型:

struct FunctionCallback
{
    template <typename F>
    static void Create(F function){}
};

FunctionCallback::Create([](float f) -> void {});

DEMO 2

关于c++ - 隐式模板参数无效,但仍可编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34242956/

相关文章:

c++ - glibmm 2.4 转换输入中的无效字节序列

templates - foreach 中的 KnockoutJS 模板

c++ - 从没有虚函数的类继承的最佳方法

c++ - 使用完后删除所有堆分配的内存是否可行?

c++ - 信号量与互斥量

c++ - 静态变量会阻碍数据缓存吗?

c++ - 监听套接字意外死亡

c++ - std::thread 构造函数?特化?。 g++ 与 clang++

c++ - 我如何创建一个模板是特定类型的编译时断言?

c++ - "auto function()"可以在函数体内有几种类型的返回吗?