Лишние скобки меняют тип переменной

Как дополнительные круглые скобки могут сказаться на типе переменной? Я, если честно, никогда не задумывался над этим. Нет, я конечно слышал про перегрузку оператора (), но сейчас не об этом. Несколько дней назад мое невнимательное отношение к круглым скобкам привело к ошибке, найти которую удалось не сразу.

Рассмотрим небольшой пример:

#include <stdio.h>

class MyClass
{
public:
  MyClass(const wchar_t* = 0){};
  
  friend MyClass& operator << (MyClass &left, const wchar_t &ch)
  {
    printf("operator\r\n");
    
    return left;
  };
};
 

int main()
{
  MyClass cl();
  cl << L'A';
  
  return 0;
}

Если попытаться его скомпилировать в g++, то будет выведено сообщение:

error: invalid operands of types ‘MyClass()’ and ‘wchar_t’ to binary ‘operator<<‘
cl << L’A’;

или в моем переводе:

ошибка: недопустимые операнды типов ‘MyClass()’ и ‘wchar_t’ бинарного оператора <<.

Данный оператор перегружен вроде бы правильно. Типы операндов тоже вроде как совпадают с типами в его объявлении (так я думал поначалу). К сожалению, я не сразу обратил внимание на «странный» тип «MyClass()» в сообщении об ошибке. Точнее я не обратил внимание на его отличие от ожидаемого «MyClass».

Компилятор, входящий в состав C++ Builder 6 выдает следующее сообщение:

E2087: Illegal use of pointer

или в моем переводе:

недопустимое использование указателя

Но у нас нет указателей. Тоже самое сообщение выдает и компилятор, входящий в состав Embarcadero RAD Studio 10.

Компилятор, входящий в состав Microsoft Visual Studio 2017 Community выдает более содержательную информацию:

 

 

Она-то и вскрывает мое заблуждение относительно типа переменной cl. Ошибка в том, что она содержит не экземпляр класса MyClass, как я ожидал, а нечто другое. Что именно? Оказывается, она задает функцию, не имеющую входных параметров и возвращающую экземпляр класса MyClass.

MyClass foo () {return MyClass();};

typeid(cl) == typeid(foo); //true

Для решения нашей проблемы нужно просто убрать лишние круглые скобки в строке 19:

MyClass cl;

Теперь наш пример работает так, как мы того и ждем.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *