【问题标题】:Variadic function - determining return type可变参数函数 - 确定返回类型
【发布时间】:2014-10-12 11:54:43
【问题描述】:

我正在使用可变参数模板,但遇到以下问题:

template <class T1, class T2>
auto sum(T1 a, T2 b) ->decltype(a + b){
    return a + b;
}
template <class T1, class T2, class... T3>
auto sum(T1 a, T2 b, T3... tail) ->decltype(a + b){
    return a + sum(b, tail...);
}

函数调用:

cout << sum(1, 2, 3, 4) << endl;    // 10 - OK
cout << sum(1.5, 2, 3, 4) << endl;  // 10.5 - OK
cout << sum(1, 2, 3.5, 4) << endl;  // 10 !! wrong result

我在这里做错了什么?

【问题讨论】:

  • 除非我在这里遗漏了什么,否则返回类型是a + b 的类型。这里,a1b2,所以返回类型是 int
  • 我尝试写 decltype(a + tail..) 但这不起作用..
  • @Tracer:“我试图写 decltype(a + tail..) 但这不起作用..” - 通过尝试这个,你的问题已经等同于这个:stackoverflow.com/questions/26274207/…

标签: c++ c++11 variadic-functions


【解决方案1】:
sum(1, 2, 3.5, 4)

前两个参数的类型为int。因此在尾随返回类型中,decltype(a + b)int,因此结果被转换为int - 并被截断。

使用std::common_type:

template <class T1, class T2, class... T3>
typename std::common_type<T1, T2, T3...>::type
  sum(T1 a, T2 b, T3... tail) 
{
    return a + sum(b, tail...);
}

注意

template <class T1, class T2, class... T3>
auto sum(T1 a, T2 b, T3... tail) ->decltype(a + sum(b, tail...))

不起作用,因为在尾随返回类型中不知道第二个模板,只有第一个模板。使用 C++14,返回类型推导是可能的:

template <class T1, class T2, class... T3>
auto sum(T1 a, T2 b, T3... tail)
{
    return a + sum(b, tail...);
}

【讨论】:

  • 在 VS 2013 中我可以同时使用这两个示例,但 clang 不会编译使用 auto & decltype 的第二个示例。那么,第二种情况是C++14特性?
  • 使用common_type 的限制是它不适用于类类型。
  • @T.C.你是对的。我可能想总结一下strings。
  • 注意common_type做了decay,C++14版本不做SFINAE。另请注意,如果需要,可以专门化 common_type
  • @Yakk 当然common_type 会衰减.. 但这在这里有多重要?此外,这里没有使用 SFINAE - 我假设不再声明称为 sum 的函数模板。还是应该将其包含在帖子中,您怎么看?
【解决方案2】:
namespace details{
  template<template<class,class>class binary_result, class T, class...Ts>
  struct nary_result{using type=T};
  template<template<class,class>class binary_result, class T0, class T1, class...Ts>
  struct nary_result<binary_result, T0,T1,Ts...>:
    nary_result<binary_result,binary_result<T0,T1>,Ts...>
  {};
}
template<template<class,class>class binary_result, class...Ts>
using nary_result=typename details::nary_result<binary_result,Ts...>::type;

template<class Lhs, class Rhs>
using binary_sum_result = decltype(std::declval<Lhs>()+std::declval<Rhs>());

template<class...Ts>
using sum_result=nary_result<binary_sum_result,Ts...>;

应该可以解决问题。

也许会添加衰减。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-29
    相关资源
    最近更新 更多