C++ 从std::function参数类型推断模板参数
为什么下面的类C++ 从std::function参数类型推断模板参数,c++,c++20,C++,C++20,为什么下面的类A无法在下面的代码中推断其模板参数: #include <functional> template <class... Ts> class A { public: using Func = std::function<void(std::decay_t<Ts>...)>; A(Func func) : m_func(func) { } private: Func m_func; };
A
无法在下面的代码中推断其模板参数:
#include <functional>
template <class... Ts>
class A
{
public:
using Func = std::function<void(std::decay_t<Ts>...)>;
A(Func func) : m_func(func)
{
}
private:
Func m_func;
};
int main()
{
//compiles
A<int, bool> a([](int, bool) {});
//does not compile with error 'class template argument deduction failed'
A b([](int, bool) {});
return 0;
}
模板参数推断传统上是函数调用表达式的独有特性。在C++17中引入之前,类模板的模板参数无法从构造函数调用中推导出来。这样,您就可以显式地指定如何从构造函数调用推导类的模板参数
template <class... Ts>
class A
{
public:
using Func = std::tuple<Ts...>;
constexpr A(Func func) : m_func(func)
{
}
private:
Func m_func;
};
template< class... Ts >
A(std::tuple< Ts... >) -> A< Ts... >;
int main()
{
std::tuple<int, bool> t;
A<int, bool> a(t);
A b(t); // deduces int, bool types from t
return 0;
}
两个问题
std::function
)在中不被考虑;这导致扣除失败
std::decay\u t
的存在导致:;那么就不能推断出Ts
#include <functional>
template <class... Ts>
class A
{
public:
using Func = std::function<void(Ts...)>;
A(Func func) : m_func(func)
{
}
private:
Func m_func;
};
int main()
{
//compiles
A<int, bool> a([](int, bool) {});
//compiles
A b(std::function([](int, bool) {}));
return 0;
}
#包括
模板
甲级
{
公众:
使用Func=std::function;
A(Func Func):m_Func(Func)
{
}
私人:
Func mu Func;
};
int main()
{
//汇编
A([](int,bool){});
//汇编
A b(std::function([](int,bool){});
返回0;
}
您认为这个问题被称为“不可推断的上下文”?您的模板实例化需要推断一个类型,该类型在通过std::decation\t
转换后产生模板实例化中使用的类型。那是无法推断的。因为lambda只是一个匿名类,所以也没有办法推断出类似的东西。@SamVarshavchik我想std::function
的推断指南可以得到somewhere@SamVarshavchik是的,std::tuple
优于std::function
,请参见EDIT1,删除std::decation\t没有帮助。这是个好消息,但您的问题到底是什么?正如我提到的,lambda也变成了匿名闭包。CTAD依赖于演绎指南。而那些推断出的东西就像旧的函数模板一样。从lambda推导std::function
的问题已经被重新讨论过了。例如,std::function([](int,bool){})
无法编译,因为它无法推断std::function
@AndreySemashev的模板参数?CTAD对它有效。那真的很酷!另外,你关于非推断上下文的第二点是不正确的,因为在使用std::detaction\t
的地方,没有模板参数推断在第一位生效。@Andreyesmashev抱歉,我不能理解你的意思;如果不删除std::decay\t
的部分,则即使将std::function
显式传递给构造函数,代码也不会编译。您的意思是使用std::decation\t
会导致由于其他原因而无法编译?
template< class R, class... Ts >
A(R (*)(Ts...)) -> A< Ts... >;
#include <functional>
template <class... Ts>
class A
{
public:
using Func = std::function<void(Ts...)>;
A(Func func) : m_func(func)
{
}
private:
Func m_func;
};
int main()
{
//compiles
A<int, bool> a([](int, bool) {});
//compiles
A b(std::function([](int, bool) {}));
return 0;
}