【问题标题】:Couldn't deduce template parameter 'T' for function arguments using std::conditional无法使用 std::conditional 推断出函数参数的模板参数“T”
【发布时间】:2017-08-23 05:44:58
【问题描述】:

鉴于这段代码:

#include <type_traits>

template<typename T>
auto sqr(typename std::conditional<sizeof(T) <= sizeof(int), T, const T&>::type a)
{return a*a;}

int main(void)
{
    auto x = sqr<int>(10); //works
    auto y = sqr(10);      //ERROR: couldn't deduce template parameter 'T'
}

调用sqr(10)时自动扣型失败是什么原因?有没有一种方法可以在不明确定义类型的情况下调用sqr()

【问题讨论】:

  • 在查看参数推导时考虑“模式匹配”。 int如何匹配std::conditionl&lt;&gt;::type模式?

标签: c++ c++11 templates type-conversion c++14


【解决方案1】:

您在这里有一个未推断的上下文。要直观说明原因,请注意 ::type 必须是 10 的实际类型,但您希望它间接依赖于 10 的类型。所以不能用参数类型推导出std::conditional的结果。

如果您寻求“优化”函数以按值传递,则解决方案是 SFINAE 重载。

template<typename T, typename = std::enable_if_t<(sizeof(T) > sizeof(int))>> // base case
auto sqr(const T& a)
{return a*a;}

template<typename T, typename = std::enable_if_t<sizeof(T) <= sizeof(int)>> // more refined case case
auto sqr(T a)
{return a*a;}

或者,为了支持更多条件,您可以使用std::enable_if_t 添加一个对 SFINAE 友好的非类型参数(例如指针)。正如@Jarod42 建议的那样:

template<typename T, std::enable_if_t<sizeof(T) <= sizeof(int), int*> = nullptr>
auto sqr(T a)
{return a*a;}

【讨论】:

  • 使用std::enable_if_t&lt;cond&gt;* = nullptr 比使用typename = std::enable_if_t&lt;cond&gt; 更好:允许添加具有不同条件的重载。
  • @Jarod42 - 谢谢。它确实更灵活。然而,我确实觉得在展示这些基于 SFINAE 的重载剔除技术时,它作为一个示例不太直观。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多