Ответ 1
Вызов функции:
std::declval<std::vector<int>>()
приводит к выражению rvalue, которое можно обозначить как:
std::vector<int>&&
Компилятор имеет две (общие) перегрузки std::begin
для выбора ([iterator.range]):
template <class C>
auto begin(C& c) -> decltype(c.begin()); // #1
template <class C>
auto begin(const C& c) -> decltype(c.begin()); // #2
Для выражения rvalue только вторая перегрузка (# 2) жизнеспособна - rvalue не может быть привязана ссылкой на константу lvalue. Константная квалификация ссылочного типа подразумевает, что компилятор будет использовать const-допустимую перегрузку функции-члена begin
:
const_iterator begin() const noexcept;
// ~~~~^
который возвращает экземпляр типа const_iterator
.
Вы можете изменить это поведение, запросив выражение lvalue std::vector<int>
из вызова std::declval
:
decltype(std::begin(std::declval<std::vector<int>&>())) pos_1 = coll.begin();
// ~~^~~