Ответ 1
Поскольку T
выводится как ссылочный тип, вам нужно использовать std::remove_reference
template<typename T, typename = decltype(&std::remove_reference_t<T>::size)>
void f3(T&&)
{}
Полный пример:
#include <vector>
#include <type_traits>
using namespace std;
template<typename T, typename = decltype(&T::size)>
void f1(T)
{}
template<typename T, typename = decltype(&T::size)>
void f2(T&)
{}
template<typename T, typename = decltype(&std::remove_reference_t<T>::size)>
void f3(T&&)
{}
int main()
{
vector<int> coll;
f1(coll); // ok
f2(coll); // ok
f3(coll); // ok
}
Как правило, при использовании ссылок на переадресацию тип утилиты модификации очень удобен; прежде всего потому, что ссылки пересылки сохраняют как категорию значений, так и cv
qualifications.
Пример 1:
-
Код ниже не удается компилировать, потому что
T
выводится какstd::vector<int>&
и вы не можете привязать неконстантную ссылку к временному вfoo
:#include <vector> template<typename T> void foo(T&&){ T nV = {3, 5, 6}; } int main(){ std::vector<int> Vec{1, 2 ,3, 4}; foo(Vec); }
-
Вы можете удалить ссылку, чтобы получить ее work:
#include <vector> template<typename T> void foo(T&&){ using RemovedReferenceT = std::remove_reference_t<T>; RemovedReferenceT nV = {3, 5, 6}; } int main(){ std::vector<int> Vec{1, 2 ,3, 4}; foo(Vec); }
Пример 2 (построенный на примере 1):
-
Просто удалить ссылку не работать в коде ниже, потому что выведенный тип переносит
const
, (aka,T
выводится какconst std::vector<int>&
) новый типRemoveReferenceT
равенconst std::vector<int>
:#include <vector> template<typename T> void foo(T&&){ using RemovedReferenceT = std::remove_reference_t<T>; RemovedReferenceT nV = {3, 5, 6}; nV[2] = 7; //woopsie } int main(){ const std::vector<int> Vec{1, 2 ,3, 4}; //note the const foo(Vec); }
-
Мы can удалим квалификаторы
cv
из типа удаленной ссылки.#include <vector> template<typename T> void foo(T&&){ using RRT = std::remove_reference_t<T>; using Removed_CV_of_RRT = std::remove_cv_t<RRT>; Removed_CV_of_RRT nV = {3, 5, 6}; nV[2] = 7; } int main(){ const std::vector<int> Vec{1, 2 ,3, 4}; foo(Vec); }
Мы можем продолжать и продолжать, мы можем объединить их в одну строку, вложив их, например: == > using D = std::remove_cv_t<std::remove_reference_t<T>>
.
Хотя есть std::decay
, который действительно мощный и короткий для такого "комбинированного удара" (но иногда вы хотите немного меньше того, что делает std::decay
).