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

时间:2014-04-11 05:06:52

标签: c++ c++11 std language-lawyer typetraits

我试图理解C ++ 11中的std::is_convertible。根据{{​​3}},std::is_convertible<T,U>::value应该评估为1 iff&#34;如果可以在返回T&的函数的return语句中使用类型U的虚构rvalue #34 ;.但是,措辞没有说明可能宣布该职能的位置。 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
}

我使用gcc-4.8.2clang-3.4(输出没有差异),我编译:

{g++|clang++} -std=c++11 -Wall -Wextra eg.cpp -o eg

此处,std::is_convertible< Ref_A, A >报告0。但是,您可以看到Fact_A::f返回类型为A的对象,并且在其return语句中使用了类型为Ref_A的右值。问题是A的复制构造函数是private,因此函数不能放在其他任何地方。相对于标准,当前行为是否正确?

第二个问题。如果我删除private,则输出将变为1 1 1。最后1是什么意思?什么是类型A&&#34;的&#34;右值?这是一个右值参考吗?因为您可能会注意到我明确删除了A的移动构造函数。因此,我无法声明Fact_A::g。但是,std::is_convertible< A&, A >报告了1

1 个答案:

答案 0 :(得分:6)

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

  

给出以下函数原型:

template <class T> typename
add_rvalue_reference<T>::type create();
     

模板专精的谓词条件is_convertible<From, To>   当且仅当以下代码中的返回表达式为止时,才应满足   格式良好,包括对返回类型的任何隐式转换   功能:

To test() {
    return create<From>();
}

并且在这里,您需要一个可移动/可复制的To:return语句应用隐式转换,如果To是类类型,则需要一个可访问的复制/移动构造函数({{1 }}不是类类型。)

与[conv] / 3

比较
  

当且仅当声明T&格式正确时,对于某些发明的临时变量e,表达式T可以隐式转换为类型T t=e;。 / p>


如果tFrom,则会出现类似

的内容
T&

,类似于To test() { return create<T&>(); } ,是左值:表达式std::declval是/产生左值,因为create<T&>()(通过T& &&)折叠为{{1 }}