std::reference_wrapper 的问题
Issue with std::reference_wrapper
问题用下面的代码就很清楚了:
#include <functional>
#include <iostream>
#include <vector>
int main() {
//std::vector<int> a, b;
int a = 0, b = 0;
auto refa = std::ref(a);
auto refb = std::ref(b);
std::cout << (refa < refb) << '\n';
return 0;
}
如果我使用注释 std::vector<int> a, b;
而不是 int a = 0, b = 0;
,则代码无法在任何 GCC 5.1、clang 3.6 或 MSVC'13 上编译。在我看来,std::reference_wrapper<std::vector<int>>
可以隐式转换为 LessThanComparable 的 std::vector<int>&
,因此它本身应该是 LessThanComparable。有人可以给我解释一下吗?
问题是 std::vector
的非成员 operator<
是函数模板:
template< class T, class Alloc >
bool operator<( const vector<T,Alloc>& lhs,
const vector<T,Alloc>& rhs );
此处进行模板类型推导时未考虑隐式转换,[temp.arg.explicit]强调if:
Implicit conversions (Clause 4) will be performed on a function argument to convert it to the type of the
corresponding function parameter if the parameter type contains no template-parameters that participate
in template argument deduction.
但在这种情况下,参数类型确实参与推导。这就是为什么找不到它的原因。如果我们编写了自己的 non-template operator<
:
bool operator<(const std::vector<int>& lhs, const std::vector<int>& rhs)
{
return true;
}
您的代码将按预期运行。不过要使用通用的,您必须明确地提取参考:
std::cout << (refa.get() < refb.get()) << '\n';
你确定
std::vector<int> a, b;
是否在做它应该做的事?以此为例
#include <functional>
#include <iostream>
#include <vector>
int main() {
std::vector<int> a, b;
//int a = 0, b = 0;
a.push_back(42);
a.push_back(6);
a.push_back(15);
for (int ii=0; ii<43; ii++) {
b.push_back(ii);
}
auto refa = std::ref(a);
auto refb = std::ref(b);
std::cout<<&refa<<std::endl;
std::cout<<&refb<<std::endl;
std::cout<<"Contents of vector A"<<std::endl;
for(auto n : a)
{
std::cout<<' '<<n;
}
std::cout<<std::endl<<"Contents of vector b: ";
for (auto n : b){
std::cout<<' '<<n;
}
//std::cout << (refa < refb) << '\n';
return 0;
}
结果是
0x7fff5fbff0c0
0x7fff5fbff0b8
Contents of vector A
42 6 15
Contents of vector b: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
最终
std::vector<int> a, b;
创建两个独立的整数向量 a 和 b,两者都没有内容;这不是用成员 a 和 b 声明单个向量的方式。
int a=0, b=0;
声明了两个单独的整数 a 和 b,每个整数的值为 0。这两个代码片段声明了完全不同的变量,不应互换使用。
问题用下面的代码就很清楚了:
#include <functional>
#include <iostream>
#include <vector>
int main() {
//std::vector<int> a, b;
int a = 0, b = 0;
auto refa = std::ref(a);
auto refb = std::ref(b);
std::cout << (refa < refb) << '\n';
return 0;
}
如果我使用注释 std::vector<int> a, b;
而不是 int a = 0, b = 0;
,则代码无法在任何 GCC 5.1、clang 3.6 或 MSVC'13 上编译。在我看来,std::reference_wrapper<std::vector<int>>
可以隐式转换为 LessThanComparable 的 std::vector<int>&
,因此它本身应该是 LessThanComparable。有人可以给我解释一下吗?
问题是 std::vector
的非成员 operator<
是函数模板:
template< class T, class Alloc >
bool operator<( const vector<T,Alloc>& lhs,
const vector<T,Alloc>& rhs );
此处进行模板类型推导时未考虑隐式转换,[temp.arg.explicit]强调if:
Implicit conversions (Clause 4) will be performed on a function argument to convert it to the type of the corresponding function parameter if the parameter type contains no template-parameters that participate in template argument deduction.
但在这种情况下,参数类型确实参与推导。这就是为什么找不到它的原因。如果我们编写了自己的 non-template operator<
:
bool operator<(const std::vector<int>& lhs, const std::vector<int>& rhs)
{
return true;
}
您的代码将按预期运行。不过要使用通用的,您必须明确地提取参考:
std::cout << (refa.get() < refb.get()) << '\n';
你确定
std::vector<int> a, b;
是否在做它应该做的事?以此为例
#include <functional>
#include <iostream>
#include <vector>
int main() {
std::vector<int> a, b;
//int a = 0, b = 0;
a.push_back(42);
a.push_back(6);
a.push_back(15);
for (int ii=0; ii<43; ii++) {
b.push_back(ii);
}
auto refa = std::ref(a);
auto refb = std::ref(b);
std::cout<<&refa<<std::endl;
std::cout<<&refb<<std::endl;
std::cout<<"Contents of vector A"<<std::endl;
for(auto n : a)
{
std::cout<<' '<<n;
}
std::cout<<std::endl<<"Contents of vector b: ";
for (auto n : b){
std::cout<<' '<<n;
}
//std::cout << (refa < refb) << '\n';
return 0;
}
结果是
0x7fff5fbff0c0
0x7fff5fbff0b8
Contents of vector A
42 6 15
Contents of vector b: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
最终
std::vector<int> a, b;
创建两个独立的整数向量 a 和 b,两者都没有内容;这不是用成员 a 和 b 声明单个向量的方式。
int a=0, b=0;
声明了两个单独的整数 a 和 b,每个整数的值为 0。这两个代码片段声明了完全不同的变量,不应互换使用。