为什么下面的类 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;
}
该类有一个 Func
类型的数据成员,需要知道其参数的类型。如何编译?
EDIT1:
我能够使用 std::tuple
进行编译:
#include <tuple>
template <class... Ts>
class A
{
public:
using Func = std::tuple<Ts...>;
constexpr A(Func func) : m_func(func)
{
}
private:
Func m_func;
};
int main()
{
std::tuple<int, bool> t;
//compiles
A<int, bool> a(t);
//do not compile with error 'class template argument deduction failed'
A b(t);
return 0;
}
答案 0 :(得分:1)
两个问题。
在 template argument deduction 中不会考虑隐式转换(从 lambda 到 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="toggle">
<a href="#" class="show_div">Show</a>
<a href="#" class="hide_div">Hide</a>
</div>
<div class="show_hide">Text</div>
<div class="show_hide">Text2</div>
<div class="show_hide">Text3</div>
<div class="show_hide">Text4</div>
<div class="show_hide">Text5</div>
</div>
<div class="container">
<div class="toggle">
<a href="#" class="show_div">Show</a>
<a href="#" class="hide_div">Hide</a>
</div>
<div class="show_hide">Text</div>
<div class="show_hide">Text2</div>
<div class="show_hide">Text3</div>
<div class="show_hide">Text4</div>
<div class="show_hide">Text5</div>
</div>
);导致扣减失败。
std::function
的存在导致 non-deduced context;那么就不能推导出 std::decay_t
。
以下代码编译。
Ts
答案 1 :(得分:0)
模板参数推导传统上是函数调用表达式的专有特性。在 C++17 中引入 deduction guides 之前,无法从构造函数调用推导出类模板的模板参数。这样,您就可以明确指定如何从构造函数调用中推导出类的模板参数。
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;
}
使用推导指南从 lambda 推导函数调用签名可能有问题。 lambda 函数没有定义与其签名对应的类型。如果 lambda 是多态的(即在其参数列表中使用 auto
),那么首先就不可能定义这种类型。并且可以使用与其签名不同的参数来调用函数,因此可能有多个不同的参数类型集,该函数可通过这些参数类型调用。在这种情况下,您很可能必须明确指定参数类型。
仍然可以从函数指针中推导出模板参数:
template< class R, class... Ts >
A(R (*)(Ts...)) -> A< Ts... >;