Есть вот такой код:
template<typename T>
struct somestruct
{
...
T somefunction(somestruct<T>* const th = this)
{
return th ? th->somefield1 : this->somefield2;
}
...
};
Компилятор VS 2017 ругается:
Ошибка C2355 "this": может указываться только в нестатических членах-функциях или инициализаторах нестатических членов данных
Объясните пожалуйста, почему я не могу подобным образом использовать this
?
Я хотел бы, чтобы вызов somepointer->somefunction(otherpointer)
возвращал поле объекта указателя из аргумента, если он не nullptr
, иначе возвращал другое поле объекта указателя, вызвавшего метод. А если somefunction
вызывается без аргументов, то это было бы аналогично вызову somepointer->somefunction(somepointer)
. Конечно, можно делать такой вызов явно или просто перегрузить somefunction
, но интересно, почему нельзя так, как я написал.
Короткий ответ: потому что в стандарте языка сказано, что так нельзя.
Длинный ответ: в языке С++ не допускается формирование значений аргументов по умолчанию на основе параметров функции.
void foo(int a, int b, int c = a + b) // Ошибка
{
...
}
this
- это тоже неявный параметр нестатического метода класса, поэтому использовать его для формирования значения аргумента по умолчанию не дозволяется. Причина этого заключается, в частности, в том, что это привело бы в необходимости вычислять параметры функции в некотором "правильном" порядке, а язык С++ не упорядочивает и никогда не упорядочивал вычисление параметров.† Это может быть не единственной причиной такого запрета.
Вместо аргумента по умолчанию вы можете просто использовать перегрузку и получить требуемый эффект
template<typename T>
struct somestruct
{
...
T somefunction(somestruct<T>* const th)
{
return th ? th->somefield1 : this->somefield2;
}
T somefunction()
{
return somefunction(this);
}
...
};
† Начиная с С++17 вычисление аргумента для неявного параметра this
упорядочено перед вычислением всех остальных аргументов. Теоретически, это должно было бы устранить вышеописанную проблему с порядком вычисления, но пока что это не привело к изменениям в спецификации использования this
в аргументах по умолчанию.
Возможно, причина заключается в том, что пока компилятор не увидел cv-квалификаторы на методе, тип this
неизвестен (т.е. неизвестно, указатель это на константный класс или нет), и поэтому его запрещено использовать до cv-квалификаторов.
Пример:
struct A
{
auto f1() const -> decltype(this) {return 0;} // Возвращает `const A *`.
auto f2() -> decltype(this) {return 0;} // Возвращает `A *`.
decltype(this) f3() const {return 0;} // Ошибка компиляции, т.к. когда компилятор видит
// `decltype(this)`, он еще не знает, константный ли это метод, и должен ли `this` быть
// `A *` или `const A *`.
decltype(this) f3() {return 0;} // Ошибка компиляции, по той же причине.
void foo(A * = this) {}; // Опять же, компилятор не знает, имеет ли `this` тип
// `A *` или `const A *, поэтому просто не дает его использовать.
}
В целом вопрос в заголовке, не знаю что ещё добавить, кроме примера
Продолжая знакомиться с Code::Blocks возник вопрос по связке его с CMakeКак в CMake назначить запускаемый проект по умолчанию ?