【问题标题】:Add implicit promotion to complex class, last step向复杂类添加隐式提升,最后一步
【发布时间】:2017-12-06 17:28:04
【问题描述】:

我想在对复数求和时允许隐式转换。 例如:

 complex<double> a; 
 complex<long double> b;
 int i;

 auto sum = a + b; // (1)
 auto SUM = a + i; // (2)

感谢回答implicit type promotion in summing two complex<>,我有启用转换的代码 (1) 为了启用(2)转换,我使用了 enable_if_t

  template <typename T, typename U>
  auto operator +(const ::std::complex<T> &a,     std::enable_if_t<std::is_arithmetic<U>::value, U>  &b) 
  {
   typedef decltype(::std::declval<T>() + ::std::declval<U>()) comcomp_t;
   typedef ::std::complex<comcomp_t> result_t;
   return ::std::operator +(result_t{a}, result_t{b});
  }

但是,我收到一个编译错误,提示“无法推断模板参数 'U'。我想我对 SFINAE 的理解很浅。任何帮助将不胜感激。谢谢

【问题讨论】:

  • 请阅读此“这需要 C++14 用于 'auto'(又名推导)返回类型。对于 C++11,您基本上必须在运算符中重复 decltype 表达式返回类型。”在其中一个答案中。
  • 我将 c++14 标志传递给编译器。我编辑了标签。谢谢

标签: c++ c++14 sfinae


【解决方案1】:

第二个参数是non-deduced context。您必须重写它,以便实际上可以推导出 U。典型的方法是将 SFINAE 粘贴到返回类型中。

 template <typename T, typename U>
 using add_t = decltype(std::declval<T>() + std::declval<U>());

 template <typename T, typename U>
 auto operator+(const std::complex<T>& a, const U& b)
     -> std::enable_if_t<std::is_arithmetic<U>::value,
                         std::complex<add_t<T, U>>>
 {
     std::complex<add_t<T, U>> res = a;
     res += b;
     return res;
 }

【讨论】:

  • 谢谢,您的解决方案看起来非常优雅。但是,由于某种原因,它无法编译。
  • @Federico 缺少&gt;
【解决方案2】:

我不确定您是否需要 SFINAE。一个最小的工作 C++14 代码是:

#include <ccomplex>
#include <type_traits>

template <typename T, typename U>
using add_t = decltype(std::declval<T>() + std::declval<U>());

template <typename T, typename U>
constexpr std::complex<add_t<T, U>> operator+(const std::complex<T>& a,
                                              const std::complex<U>& b) noexcept
{
  using returnType = decltype(a + b);
  return returnType(a.real() + b.real(), a.imag() + b.imag());
}

template <typename T, typename U>
constexpr std::complex<add_t<T, U>> operator+(const std::complex<T>& a,
                                              const U& b) noexcept
{
  using returnType = decltype(a + b);
  return returnType(a.real() + b, a.imag());
}

template <typename T, typename U>
constexpr auto operator+(const T& a, const std::complex<U>& b) noexcept
{
  return b + a;  // assume commutativity of + operator
}

using namespace std;

int main()
{

  constexpr complex<double> a;
  constexpr complex<long double> b;
  constexpr int i = 1;

  constexpr auto s1 = a + b;  // (1)
  constexpr auto s2 = a + i;  // (2)
  constexpr auto s3 = i + a;  // (3)
  constexpr auto s4 = a + 2;  // (4)
  constexpr auto s5 = 2 + a;  // (5)
}

注意:它也适用于 constexpr 表达式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多