c++ - 当向 std::enable_if 传递错误类型(double)而不是 std::complex 时,std::enable_if 无法执行操作

标签 c++ c++11 templates sfinae complex-numbers

我想让我的数组类从 double 复制数据数组到std::complex<double> (或任何 U 到 std::complex)带有 operator= 的数组。为此,我使用了 std::enable_if 。然而,它未能检测到它不应该被使用。

以下函数,如果输入T,我想被调用是什么复杂的东西。所以我使用了条件std::is_same<T, std::complex<typename T::value_type> ,因为std::complex将其使用的类型存储在 ::value_type 中。该函数的定义如下:

template <typename T, int S>
typename std::enable_if<std::is_same<T, std::complex<typename T::value_type> >::value, MyArray<T,S>& >::type
MyArray<T,S>::operator=(const typename std::enable_if<std::is_scalar<typename T::value_type>::value, MyArray<typename T::value_type>&, S >::type rhs)

但是,如果我尝试复制 MyArray<double>,则会出现以下错误。显然它未能检测到 double不是`

error: 'double' is not a class, struct, or union type MyArray::operator=(const typename std::enable_if::value, MyArray&, S >::type rhs)

我在这里做错了什么?


更新:

我想让我想要实现的目标变得清晰,因为(抱歉)有太多的困惑。

我需要执行此操作:

MyArray<double> d;
MyArray<std::complex<double>> cd;
cd = d;

最佳答案

不太明白,但是...如果您想启用 operator=()仅当传入MyArray<T>时与T那是 std::complex<U> ,你为什么不简单地写

   template <typename F>
     MyArray & operator= (MyArray<std::complex<F>> const & rhs)
      { return *this }

--编辑--

I want to assign U to std::complex<U>, so MyArray<std::complex<U>> = MyArray<U>.

所以你想要完全相反的东西。

我想你可以做类似的事情

#include <complex>
#include <type_traits>

template <typename T>
struct MyArray
 {
   template <typename U>
   typename std::enable_if<std::is_same<T, std::complex<U>>::value,
         MyArray &>::type 
      operator= (MyArray<U> const & rhs)
       { return *this; }
 };

int main()
 {
   MyArray<double> d;
   MyArray<std::complex<double>> cd;
   cd = d;
 }

-- 编辑 2--

but there's a second template parameter that I removed in the original question, thinking that I'm simplifying the issue for readability. But it was wrong of me to do that, because partial specializations of functions are not allowed in C++. So my template is template , not template , which is very different

我认为没有必要部分特化

#include <complex>
#include <type_traits>

template <typename T, int S>
struct MyArray
 {
   template <typename U>
   typename std::enable_if<std::is_same<T, std::complex<U>>::value,
        MyArray &>::type 
    operator= (MyArray<U, S> const & rhs)
     { return *this; }
 };

int main()
 {
   MyArray<double, 3> d;
   MyArray<std::complex<double>, 3> cd;
   cd = d;
 }

如果问题出在定义operator()在类(class)主体之外,我提出以下修改后的示例

#include <complex>
#include <type_traits>

template <typename T, int S>
struct MyArray
 {
   template <typename U>
   typename std::enable_if<std::is_same<T, std::complex<U>>::value,
        MyArray &>::type 
    operator= (MyArray<U, S> const & rhs);
 };

template <typename T, int S>
template <typename U>
typename std::enable_if<std::is_same<T, std::complex<U>>::value,
      MyArray<T, S> &>::type 
   MyArray<T, S>::operator= (MyArray<U, S> const & rhs)
      { return *this; }

int main()
 {
   MyArray<double, 3> d;
   MyArray<std::complex<double>, 3> cd;
   cd = d;
 }

-- 编辑 3--

Is there a way to do the same with the copy constructor? [...] It's quite tricky and seems impossible because there's no return type.

是的,有办法

#include <complex>
#include <type_traits>

template <typename T, int S>
struct MyArray
 {
   template <typename U>
   typename std::enable_if<std::is_same<T, std::complex<U>>::value,
         MyArray &>::type 
      operator= (MyArray<U, S> const & rhs)
       { return *this; }

   template <typename U,
            typename = typename std::enable_if<std::is_same<T,
                           std::complex<U>>::value>::type>
   MyArray (MyArray<U, S> const & rhs)
    { }

   MyArray() = default;
   MyArray(MyArray const &) = default;
   MyArray(MyArray &&) = default;
   ~MyArray() = default;
 };

int main()
 {
   MyArray<double, 3> d;                      // need MyArray() = default
   MyArray<double, 3> d2(d);                  // OK
   MyArray<float, 3> f;                       // OK
   MyArray<std::complex<double>, 3> cd(d);    // OK
   //MyArray<std::complex<double>, 3> cd2(f); // error!
   cd = d;

 }

遵守= default添加线路;如果没有第一个(我不知道其他三个是否有用),代码将无法编译,因为(如果我理解正确的话)SFINAE 复制构造函数禁用(删除)默认复制构造函数,因此删除其他默认构造函数并默认析构函数。

关于c++ - 当向 std::enable_if 传递错误类型(double)而不是 std::complex 时,std::enable_if 无法执行操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39981597/

相关文章:

c++ - 检测地址(主机)是否解析为本地计算机

c++ - Memcpy 导致 block 释放两次错误

c++ - 非静态数据成员初始化

c++ - 为什么我的初始化列表对于类型推导是半忽略的?

C++模板非类型参数类型推导

c++ - 为什么模板只能在头文件中实现?

c++ - 如何编写C++模板函数在内部调用多个C函数?

c++ - VS2010是否预先计算#define定义的预处理器?

c++ - 如何用 ffi 包装自定义结构的 std::vector?

c++ - 顺序文件访问,使用 C++ 在项目目录中加载多个文本文件