为什么转发参考在这种情况下不起作用?
Why doesn't forwarding reference work in this case?
#include <vector>
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(&T::size)>
void f3(T&&)
{}
int main()
{
vector<int> coll;
f1(coll); // ok
f2(coll); // ok
f3(coll); // error : no matching function for call to 'f3'
}
main.cpp(21,6): note: candidate template ignored: substitution failure [with T
= >
std::vector<int, std::allocator<int> > &
]: type
'std::vector<int, std::allocator<int> > &
' cannot be used prior to
'::
' because it has no members
void f3(T&&)
我的编译器是 clang 4.0。
令我惊讶的是,f3(coll)
失败了,而 f1(coll)
和 f2(coll)
都正常。
为什么转发引用在这种情况下不起作用?
因为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
}
通常,当使用转发引用时、type modification utilities comes in very handy; primarily because forwarding references preserves both value category and 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);
}
我们 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
所做的 std::decay
that is really powerful and short for such "combo kick" (but sometimes you want a little less。
#include <vector>
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(&T::size)>
void f3(T&&)
{}
int main()
{
vector<int> coll;
f1(coll); // ok
f2(coll); // ok
f3(coll); // error : no matching function for call to 'f3'
}
main.cpp(21,6): note: candidate template ignored: substitution failure [with
T
= >std::vector<int, std::allocator<int> > &
]: type 'std::vector<int, std::allocator<int> > &
' cannot be used prior to '::
' because it has no members
void f3(T&&)
我的编译器是 clang 4.0。
令我惊讶的是,f3(coll)
失败了,而 f1(coll)
和 f2(coll)
都正常。
为什么转发引用在这种情况下不起作用?
因为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
}
通常,当使用转发引用时、type modification utilities comes in very handy; primarily because forwarding references preserves both value category and 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); }
我们 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
所做的 std::decay
that is really powerful and short for such "combo kick" (but sometimes you want a little less。