2016-10-11 11 views
2

Я хотел бы, чтобы мои данные массива массива копировали из double массивов в std::complex<double> (или любой U в std :: сложные) массивы с operator=. Для этого я использовал std::enable_if. Однако он не обнаружил, что его не следует использовать.std :: enable_if не работает, когда вместо него передается неправильный тип (double), а не std :: complex

Следующая функция, я хочу, чтобы ее вызывали, если тип 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)

Что я здесь делаю неправильно?


UPDATE:

Я хочу сделать то, что я хочу для того чтобы достигнуть ясно, потому что (извините), есть так много путаницы.

Мне нужна эта операция будет возможна:

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

Можете ли вы показать нам весь ваш код? Есть ли у вас другие перегрузки 'operator ='? – refi64

+0

Эти швы слишком сложны. Не 'template MyArray MyArray :: operator = (const std :: complex & rhs)' делать то, что вы хотите? – NathanOliver

+0

@ kirbyfan64sos Весь код действительно, действительно огромный. Я рад добавить любые бит, которые вам нужны. Да, есть еще один 'operator =', но это стандартный 'operator =' ничем особенным. –

ответ

2

Не уверен, что понять, но ... если вы хотите позволить вашему operator=() только тогда, когда входящий MyArray<T> это с T, что является std::complex<U>, почему не вы просто написать

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

--EDIT--

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; 
} 

- EDIT 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() outsi де тело класса, я предлагаю следующее, модифицированный пример

#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; 
} 

- EDIT 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 отключает (удаляет) конструктор копии по умолчанию, поэтому удаляет другие конструкторы по умолчанию и деструктор по умолчанию.

+0

Смотрите комментарий к теме Q. Это не то, чего хочет OP. У меня была такая же мысль и спросила. – NathanOliver

+0

Мне нужна противоположность. Проверьте обновление. –

+0

@NathanOliver - видно и исправлено; Благодарю. – max66

1

Что-то я считаю, помогает при попытке понять проблемы шаблон попробуйте заменить самостоятельно:

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

очевидно ли сейчас? Если double - ваш тип T, то T будет использоваться в вашей логике SFINAE выше. Но double не имеет ::value_type.

Вы могли бы попробовать что-то вроде этого:

template<typename T> 
typename std::enable_if<std::is_scalar<T>, MyArray<T>&>::type 
    MyArray<T>::operator=(const std::complex<T>& rhs){...} 

И если вам не нужен is_scalar чек, используйте ответ max66 вместо этого.

Обновление:
Okey-dokey. Таким образом, этот должен адрес, желающий перейти от MyArray<T> к MyArray<std::complex<T>> через оператор присваивания, а не наоборот.

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

Хитрость здесь в том, что int и std::complex<int> не тот же тип. Вы также можете сделать это, заменив T::value_type на U. Наконец, вы можете сделать это, частично специализировав свой класс MyArray<T> для случаев, когда это класс MyArray<std::complex<T>>, который, если вам когда-либо понадобится больше вещей, как то, что вы просите, может быть стоит рассмотреть.

+0

Мне нужно наоборот. Проверьте обновление. –

+0

Не могли бы вы подумать о существовании второго параметра шаблона 'int'? Я думаю, что это источник проблемы. Пожалуйста, взгляните на обновленный код, который я поставил в моем вопросе. –

+0

@TheQuantumPhysicist. Ваш обновленный код, который вы помещаете в свой вопрос, показывает, используя «double» в качестве примера ... Что значит второй параметр шаблона 'int'? – Altainia

 Смежные вопросы

  • Нет связанных вопросов^_^