Mat*_*vid 7 c++ std type-traits language-lawyer c++11
我试图std::is_convertible
在C++ 11中理解.根据cppreference.com,std::is_convertible<T,U>::value
应该评估为1 iff"如果T
在返回的函数的return语句中可以使用类型的假想rvalue U
".但是,措辞没有说明可能宣布该职能的位置.当复制构造函数U
是私有时,人们应该期待什么?人们期待什么T
是左值参考?
例如,考虑以下代码:
#include <iostream>
#include <type_traits>
struct Fact_A;
struct A {
friend struct Fact_A;
A() = default;
A(A&&) = delete;
private:
A(const A&) = default;
};
struct Ref_A {
A* _ptr;
Ref_A(A* ptr) : _ptr(ptr) {}
operator A& () { return *_ptr; }
};
struct Fact_A {
static A* make_A(const A& a) { return new A(a); }
static A f(A* a_ptr) { return Ref_A(a_ptr); }
//static A g(A&& a) { return std::move(a); }
};
int main() {
A a1;
A* a2_ptr = Fact_A::make_A(a1);
(void)a2_ptr;
std::cout << std::is_convertible< Ref_A, A >::value << "\n" // => 0
<< std::is_convertible< Ref_A, A& >::value << "\n" // => 1
<< std::is_convertible< A&, A >::value << "\n"; // => 0
}
Run Code Online (Sandbox Code Playgroud)
我正在使用gcc-4.8.2
或clang-3.4
(输出没有区别),我编译:
{g++|clang++} -std=c++11 -Wall -Wextra eg.cpp -o eg
Run Code Online (Sandbox Code Playgroud)
在这里,std::is_convertible< Ref_A, A >
报道0
.但是,您可以看到Fact_A::f
返回一个类型的对象A
,并Ref_A
在其return语句中使用了一个rvalue类型.问题是复制构造函数A
是private
,所以函数不能放在其他任何地方.目前的行为是否与标准相符?
第二个问题.如果我删除private
,输出变为1 1 1
.最后的1
意思是什么?什么是"rvalue of type A&
"?这是一个右值参考吗?因为您可能会注意到我明确删除了移动构造函数A
.因此,我无法申报Fact_A::g
.但std::is_convertible< A&, A >
报道仍然如此1
.
is_convertible
在[meta.rel]/4中从n3485定义如下:
给出以下函数原型:
Run Code Online (Sandbox Code Playgroud)template <class T> typename add_rvalue_reference<T>::type create();
is_convertible<From, To>
当且仅当以下代码中的返回表达式格式正确时,才应满足模板特化的谓词条件,包括对函数返回类型的任何隐式转换:Run Code Online (Sandbox Code Playgroud)To test() { return create<From>(); }
在这里,你需要一个可移动/可复制的To
:return语句应用一个隐式转换,如果To
是类类型(T&
不是类类型),这需要一个可访问的复制/移动构造函数.
与[conv]/3比较
对于某些发明的临时变量,当且仅当声明格式正确时,表达式才
e
可以隐式转换为类型.T
T t=e;
t
如果From
是T&
,你会得到类似的东西
To test() {
return create<T&>();
}
Run Code Online (Sandbox Code Playgroud)
其中,类似于std::declval
左值:表达式create<T&>()
是/产生左值,因为T& &&
(via add_rvalue_reference
)被折叠为T&
.