Страницы

Поиск по вопросам

вторник, 13 ноября 2018 г.

CLion не воспринимает запись вида `T const& a` при описании функции

Есть некоторый класс Vector2 с перегруженным оператором (возможно аналогичное поведение и с обычными ф-циями, но из-за непредсказуемого поведения (об этом позже) достоверно проверить не удалось):
template class Vector2 { ... template // объявляем дружественную ф-цию шаблонной friend Vector2 operator +(Vector2 const& l_v, Vector2 const& r_v); ... }
Обращу внимание на форму записи константной ссылки - T const& a, а не const T& val. Потом это будет играть важную роль.
Но при попытке описать эту ф-цию, а именно:
template Vector2 operator +(Vector2 const& l_v, Vector2 const& r_v) { ... }
начинается самое интересное, а именно абсолютно непредсказуемое поведение анализа кода "на лету", от подобных генераций кода при попытке автоматической реализации объявленной ф-ции:
template Vector2 operator+(Vector2 < T >
const & l_v,
Vector2 const& r_v
) { return Vector2(); } // да-да, именно в таком виде, со всеми отступами
до категоричного отказа анализировать код, подчёркивая каждое второе слово красным цветом.
В целом, иногда (очень редко), CLion воспринимает всё правильно, но через время снова начинает деградировать.
А теперь к T const& a. Дело в том, что если поменять именно в описании ф-ции запись на const T& a, то всё будет работать более чем нормально. Вид записи в объявлении ф-ции никак не влияет.

Безусловно, можно было бы просто перейти на запись вида const T& a, да и код-то компилируется, и это лишь визуальная помощь от данной IDE, но я бы не стал писать этот вопрос, если бы не хотел решить эту проблему, поэтому хотелось бы понять, как это возможно сделать.

P.S. CLion версии 2018.1, но также проверялось на 2018.1.6, на другом устройстве, где результат был таким же.


Ответ

Так как в функции и левый операнд и правый имеют тип класса, то такую функцию другом обьявить бессмысленно.
Во вторых, если работа ыункции никак не связана с состоянием обьекта, и результатом функции является совершенно другой обьект, то вообше лучше избавить интерфейс класса от этой функции и определить ее отдельно (но в одном модуле). Например:
class Integer { int k; public: Integer(int n = 0) : k(n){} //модификаторы //т.е. мы изменяем состояние обьекта *this Integer& operator +=(const Integer& r_v) { k += r_v.k; return *this; } //... //селекторы int get_data() const { return k; } // функция выдает состояние обьекта }; // operator+ (и подобные методы) определяем вне класса inline Integer operator +(const Integer& l_v, const Integer& r_v) { Integer t(l_v); t += r_v; return t; }
Такой подход избавляет класс от лишнего интерфейса и наиболее логичен. И если этот подход применить в написании вашего класса, то все становится гораздо проще...
template class Vector2 { //... public: Vector2& operator +=(Vector2 const& r_v);
}; template inline Vector2 operator +(Vector2 const& l_v, Vector2 const& r_v) {...}

Комментариев нет:

Отправить комментарий