Поскольку 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
}
Demo
Как правило, при использовании Ссылки на пересылку, type modification utilities очень удобно; прежде всего потому, что ссылки на пересылку сохраняет как value category, так и cv
qualifications.
Пример 1:
Код ниже fails для компиляции, потому что 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):
Простое удаление ссылки будет not work в коде ниже, потому что выведенная тип несет const
квалификацию, (он же, 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);
}
We 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);
}
Мы можем пойти дальше и дальше, причины, мы можем combine их в одну линию, вкладывая их, как: ==>using D = std::remove_cv_t<std::remove_reference_t<T>>
.
Хотя есть std::decay
, что это действительно мощный и short для такого «комбо-удар» (но иногда вы хотите a little less что std::decay
делает).
Сообщите нам об ошибке. – user2079303
@ user2079303, см. Мое обновление. – xmllmx
Что неясно о сообщении об ошибке? –