具有私有拷贝构造函数的C++ 11 std :: is_convertible行为

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.2clang-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类型.问题是复制构造函数Aprivate,所以函数不能放在其他任何地方.目前的行为是否与标准相符?

第二个问题.如果我删除private,输出变为1 1 1.最后的1意思是什么?什么是"rvalue of type A&"?这是一个右值参考吗?因为您可能会注意到我明确删除了移动构造函数A.因此,我无法申报Fact_A::g.但std::is_convertible< A&, A >报道仍然如此1.

dyp*_*dyp 6

is_convertible 在[meta.rel]/4中从n3485定义如下:

给出以下函数原型:

template <class T> typename
add_rvalue_reference<T>::type create();
Run Code Online (Sandbox Code Playgroud)

is_convertible<From, To> 当且仅当以下代码中的返回表达式格式正确时,才应满足模板特化的谓词条件,包括对函数返回类型的任何隐式转换:

To test() {
    return create<From>();
}
Run Code Online (Sandbox Code Playgroud)

在这里,你需要一个可移动/可复制的To:return语句应用一个隐式转换,如果To是类类型(T&不是类类型),这需要一个可访问的复制/移动构造函数.

与[conv]/3比较

对于某些发明的临时变量,当且仅当声明格式正确时,表达式才e可以隐式转换为类型.TT t=e;t


如果FromT&,你会得到类似的东西

To test() {
    return create<T&>();
}
Run Code Online (Sandbox Code Playgroud)

其中,类似于std::declval左值:表达式create<T&>()是/产生左值,因为T& &&(via add_rvalue_reference)被折叠为T&.