简体   繁体   English

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

[英]C++11 std::is_convertible behaviour with private copy constructor

I'm trying to understand std::is_convertible in C++11. 我试图理解C ++ 11中的std::is_convertible According to cppreference.com , std::is_convertible<T,U>::value should evaluate to 1 iff "If an imaginary rvalue of type T can be used in the return statement of a function returning U ". 根据cppreference.comstd::is_convertible<T,U>::value应该计算为1 iff“如果在返回U的函数的return语句中可以使用类型为T的虚构rvalue”。 The wording says nothing about where that function might be declared, though. 但是,措辞没有说明可能宣布该职能的位置。 What should one expect when the copy constructor of U is private? U的复制构造函数是私有的时,应该期待什么? What should one expect when T is an lvalue reference? T是左值参考时,人们应该期待什么?

Eg, consider this code: 例如,考虑以下代码:

#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
}

I'm using gcc-4.8.2 or clang-3.4 (no difference in output), and I compile with: 我正在使用gcc-4.8.2clang-3.4 (输出没有区别),我用以下代码编译:

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

Here, std::is_convertible< Ref_A, A > reports 0 . 这里, std::is_convertible< Ref_A, A >报告0 However, you can see that Fact_A::f returns an object of type A , and an rvalue of type Ref_A is used in its return statement. 但是,您可以看到Fact_A::f返回A类型的对象,并且在其return语句中使用了类型为Ref_A的rvalue。 The problem is that the copy constructor of A is private , so that function cannot be placed anywhere else. 问题是A的复制构造函数是private ,因此函数不能放在其他任何地方。 Is the current behaviour correct with respect to the standard? 目前的行为是否与标准相符?

Second question. 第二个问题。 If I remove private , the output turns into 1 1 1 . 如果我删除private ,输出变为1 1 1 What does the last 1 mean? 最后1是什么意思? What is an "rvalue of type A& "? 什么是“ A&A& r价”? Is that an rvalue reference? 这是一个右值参考吗? Because you might notice I explicitly deleted the move constructor of A . 因为您可能会注意到我明确删除了A的移动构造函数。 As a result of this, I cannot declare Fact_A::g . 因此,我无法声明Fact_A::g But still, std::is_convertible< A&, A > reports 1 . 但是, std::is_convertible< A&, A >报告1

is_convertible is defined as follows in [meta.rel]/4 from n3485: is_convertible在[meta.rel] / 4中从n3485定义如下:

Given the following function prototype: 给出以下函数原型:

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

the predicate condition for a template specialization is_convertible<From, To> shall be satisfied if and only if the return expression in the following code would be well-formed, including any implicit conversions to the return type of the function: 当且仅当以下代码中的返回表达式is_convertible<From, To>才会满足模板特化的谓词条件is_convertible<From, To> ,包括对函数返回类型的任何隐式转换:

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

and here, you need a movable/copyable To : The return-statement applies an implicit conversion, and this requires an accessible copy/move constructor if To is a class type ( T& is not a class type). 在这里,你需要一个可移动/可复制的To :return语句应用一个隐式转换,如果To是类类型( T&不是类类型),这需要一个可访问的复制/移动构造函数。

Compare to [conv]/3 与[conv] / 3比较

An expression e can be implicitly converted to a type T if and only if the declaration T t=e; 当且仅当声明T t=e;表达式e可以隐式转换为类型T is well-formed, for some invented temporary variable t . 对于一些发明的临时变量t


If From is T& , you get something like 如果FromT& ,你会得到类似的东西

To test() {
    return create<T&>();
}

which, similar to std::declval , is an lvalue: The expression create<T&>() is/yields an lvalue, since T& && (via add_rvalue_reference ) is collapsed to T& . std::declval类似,它是一个左值:表达式create<T&>()是/产生一个左值,因为T& && add_rvalue_reference (通过add_rvalue_reference )折叠为T&

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM