Я пытаюсь понять синтаксис объявления новой функции на основе конечного возврата в C ++ 11, используя decltype.
В следующем коде я пытаюсь определить функцию-член, возвращающую const & чтобы разрешить доступ только для чтения в i
#include <iostream>
#include <type_traits>
struct X {
int &i;
X(int &ii) : i(ii) {}
// auto acc() const -> std::add_const<decltype((i))>::type { return i; } // fails the constness test
auto acc() const -> decltype(i) { return i; } // fails the constness test
// const int &acc() const { return i; } // works as expected
};
void modify_const(const X &v) {
v.acc() = 1;
}
int main() {
int i = 0;
X x(i);
modify_const(x);
std::cout << i << std::endl;
return 0;
}
Как уже упоминалось в комментариях, только последняя закомментированная версия acc()
работает, тогда как при использовании других код просто компилирует и печатает значение 1
,
Вопрос: Как мы должны определить acc()
функция с использованием нового синтаксиса объявления функции на основе decltype
, такой, что компиляция здесь не удается из-за возврата const &int
в modify_const
или, другими словами, такой, что acc()
имеет надлежащий const &int
тип возврата.
замечание: с помощью int i;
вместо int &i;
в качестве переменной-члена в X
выдает ошибку компиляции, как и ожидалось.
отредактированный чтобы лучше различать постоянство v
а также X::i
соответственно. Это последнее, что я пытаюсь навязать в acc()
,
Проблема в том, что decltype((i))
вернуть int&
и применить const
на этот тип не влияет. Вы хотите что-то вроде
template <typename T> struct add_ref_const { typedef T const type; };
template <typename T> struct add_ref_const<T&> { typedef T const& type; };
… а затем использовать
auto acc() const -> typename add_ref_const<decltype((i))>::type { return i; }
Это const
должен идти между типом T
и &
, Решение было бы очевидным, если бы вы поставили const
в правильное место: const
должен идти направо.
В этом нет ничего противозаконного const
функция-член, изменяющая цель указателя на неконстантную, даже если этот указатель был получен из переменной-члена.
С точки зрения компилятора, int&
Это правильный тип возврата.
Ваш «modify_const
msgstr «функция неверно названа. i
это то, что модифицируется, а не const
,
Просто добавьте & налево и пропустите завершающий тип возврата.
struct X {
int &i;
X(int &ii) : i(ii) {}
auto& acc() const { return i; } // Returns const reference
auto& acc() { return i; } // Returns non-const reference
const auto& acc() const { return i; } // Add const to the left to make it even more readable
};
Обратите внимание, что используя этот синтаксис, вы можете объявить переменную-член после того, как объявили функцию.