这是相关代码的链接:
#include <iostream>
#include <string>
#include <vector>
#include <type_traits>
int main()
{
std::vector<int> v{1, 2, 3, 4, 5};
auto iter = begin(std::move(v));
if(std::is_const<typename std::remove_reference<decltype(*iter)>::type>::value)
std::cout<<"is const\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
http://coliru.stacked-crooked.com/a/253c6373befe8e50
我遇到了这种行为,因为declval<Container>()在decltype表达式中std::begin.gcc和clang都返回迭代器,在解除引用时会产生const引用.它可能是有意义的,因为r值引用通常绑定到您不想变异的过期对象.但是,我找不到任何关于此的文件来确定它是否符合标准.我找不到任何相关的重载begin()或重新限定的重载Container::begin().
更新:答案澄清了正在发生的事情,但相互作用可能很微妙,如下所示:
#include <iostream>
#include <string>
#include <vector>
#include <type_traits>
int main()
{
if(std::is_const<typename std::remove_reference<decltype(*begin(std::declval<std::vector<std::string>>()))>::type>::value)
std::cout<<"(a) is const\n";
if(!std::is_const<typename std::remove_reference<decltype(*std::declval<std::vector<std::string>>().begin())>::type>::value)
std::cout<<"(b) is not const\n";
if(!std::is_const<typename std::remove_reference<decltype(*begin(std::declval<std::vector<std::string>&>()))>::type>::value)
std::cout<<"(c) is not const\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
http://coliru.stacked-crooked.com/a/15c17b288f8d69bd
天真地,你不会期望(a)和(b)的不同结果当:: begin刚刚用调用vector :: begin来定义时.但是缺少std :: begin重载,它采用非const …
以下面的课程为例
#include <iostream>
using namespace std;
class A{
private:
int a_;
int b_;
A(const A&) = delete;
A& operator=(const A&) = delete;
A(A&&) = delete;
A& operator=(A&&) = delete;
public:
A(int a, int b) : a_{a}, b_{b}{cout<<"constructed\n";}
void ephemeral() const{cout<<"operation\n";}
~A(){cout<<"destructed\n";}
};
A make_A(int a, int b){
return {a, b};
}
int main(){
make_A(1, 2).ephemeral();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
构造对象,执行操作,然后对其进行破坏.
但是,我担心这是否有保证.我主要担心的是,由于标准给予编译器的自由,我是否能看到任何我不知道的影响.
我不认为copy-elision是一个因素,因为所有的移动和复制构造函数都被声明删除,所以它们怎么能被调用?
被调用的唯一构造函数是带有两个整数的构造函数.我可以确定这在编译器,平台和优化级别上的表现是否一致?
我怀疑答案是肯定的,但可能会有微妙之处.