2015-02-20 3 views
11

Использование gcc 4.9 я обнаружил, что типы, созданные с типом буквального для комплексных чисел не являются такими же, как при создании обычными средствами, а именно:TypeId (комплекс <double> (0.0,1.0)) = TypeId (1.0i)

typeid(complex<double>(0.0,1.0)) != typeid(1.0i) 
  1. Я делаю ошибку здесь?
  2. Является ли это ошибкой компилятора или стандартным поведением?
  3. Если предполагаемое стандартное поведение: в чем причина?

Добавление недостающего MCVE

#include <complex> 
using std::complex; 
using namespace std::literals::complex_literals; 

#include <iostream> 
using std::cout; 
using std::endl; 

#include <typeinfo> 

int main(int argc, char* argv[]) { 
    if (typeid(complex<double>(0.0, 1.0)) == typeid(1.0i)) 
     cout << "types are same as expected" << endl; 
    else 
     cout << "types are unexpectedly not the same" << endl; 

    cout << 1.0i*1.0i << endl; 
    cout << complex<double>(0.0, 1.0)*complex<double>(0.0, 1.0) << endl; 
} 

Compile инструкции:

g++ -std=gnu++14 complex.cpp -o complex.exe 

Выход:

types are unexpectedly not the same 
1 
(-1,0) 

Интересно, что буквальное не даже, кажется, правильное мнимое число. (Я уверен, что я с видом что-то ...)

+0

Любой шанс, который вы можете поместить в исходный список, который фактически компилируется? Я * думаю * вы используете 'std :: complex ', который отличается от '_Complex', gnu-extension для мнимых констант, но без MCVE его жесткое высказывание * что * вы на самом деле делаете. – WhozCraig

+0

Спасибо за обновление. да, они разные. Один раз из стандартной библиотеки, другой - из расширения компилятора. – WhozCraig

+2

[Невозможно воспроизвести проблему в C++ 14] (http://coliru.stacked-crooked.com/a/1fbd46340ab9b14e) @WhozCraig «i» является (также?) Буквальным суффиксом в C++ 14. В режиме C++ 11 gcc, вероятно, использует [это расширение] (https://gcc.gnu.org/onlinedocs/gcc/Complex.html) – dyp

ответ

20

поведения программы зависит от стандартного режима языка НКИ:

Существует В gcc extension for a built-in literal suffix i, который производит C99 комплексных чисел. Они отличаются встроенными типами _Complex double, в отличие от «определяемого пользователем» класса (специализация шаблона) std::complex<double>, используемого в C++.

В C++ 14, C++ теперь имеет определяемый пользователем литеральный суффикс i для комплексных чисел. То есть, функция complex<double> operator"" i(long double) внутри встроенного пространства имен std::literals::complex_literals.

Эти два буквальных суффиксы конкурируя:

  • В ++ режиме C 11, только встроенный расширение возможно, но является расширением. Следовательно, gcc разрешает его только в режиме -std=gnu++11 и даже предупреждает об этом. Как ни странно, clang позволяет это даже в режиме -std=c++11.

  • В строгого режима C++ 14 (-std=c++14 или -std=c++1y), встроенные в расширение должно быть отключено, чтобы удалить двусмысленность (насколько я могу сказать), следовательно, как GCC и лязг выбирающего определенного пользователя буквальный суффикс.

  • В режиме gnu-extension-C++ 14 -std=gnu++14 gcc выбирает встроенный суффикс (для обратной совместимости?), Тогда как clang выбирает суффикс, определенный пользователем. Это выглядит странно, и я предлагаю искать или регистрировать отчеты об ошибках здесь.

В зависимости от которого выбирается буквальным суффикс, вы либо получите встроенный тип _Complex double или какой-то std::complex<double>.

+0

Отличный ответ. Я все время забываю, что пользовательские литералы попали под зонтик. – WhozCraig

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