2014-04-11 13 views
7

Tôi đang cố gắng hiểu std::is_convertible trong C++ 11. Theo cppreference.com, std::is_convertible<T,U>::value nên đánh giá thành 1 iff "Nếu có thể sử dụng giá trị tưởng tượng của loại T trong câu lệnh trả về của hàm trả về U". Từ ngữ nói không có gì về nơi mà chức năng đó có thể được tuyên bố, mặc dù. Điều gì sẽ xảy ra khi người xây dựng bản sao của U là riêng tư? Bạn nên mong đợi điều gì khi T là tham chiếu giá trị l?C++ 11 std :: hành vi is_convertible với hàm tạo bản sao riêng

Ví dụ: xem xét mã này:

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

Tôi đang sử dụng gcc-4.8.2 hoặc clang-3.4 (có sự khác biệt về sản lượng), và tôi biên dịch với:

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

Ở đây, std::is_convertible< Ref_A, A > báo cáo 0. Tuy nhiên, bạn có thể thấy rằng Fact_A::f trả về một đối tượng thuộc loại A và một giá trị bằng loại Ref_A được sử dụng trong báo cáo trả về của nó. Vấn đề là các nhà xây dựng bản sao của Aprivate, do đó, chức năng đó không thể được đặt bất cứ nơi nào khác. Hành vi hiện tại có đúng với tiêu chuẩn không?

Câu hỏi thứ hai. Nếu tôi xóa private, đầu ra sẽ chuyển thành 1 1 1. 1 có nghĩa là gì? "Rvalue loại A&" là gì? Đó có phải là một tham chiếu rvalue? Bởi vì bạn có thể nhận thấy tôi đã xóa một cách rõ ràng hàm khởi tạo của A. Do đó, tôi không thể khai báo Fact_A::g. Nhưng vẫn còn, std::is_convertible< A&, A > báo cáo 1.

Trả lời

6

is_convertible được định nghĩa như sau trong [meta.rel]/4 từ n3485:

Với chức năng nguyên mẫu sau:

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

điều kiện vị cho một mẫu chuyên môn is_convertible<From, To> chịu hài lòng khi và chỉ khi biểu thức trả về trong mã sau sẽ là được tạo đúng, bao gồm mọi chuyển đổi tiềm ẩn đối với loại trả về chức năng:

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

và ở đây, bạn cần có một/copyable To động: Sự trở lại-tuyên bố áp dụng một chuyển đổi ngầm, và điều này đòi hỏi phải có một constructor sao chép/di chuyển truy cập được nếu To là một loại lớp (T& được không phải là một lớp kiểu).

So với [conv]/3

Một biểu e có thể được ngầm chuyển đổi sang một loại T nếu và chỉ nếu việc kê khai T t=e; là tốt được hình thành, đối với một số phát minh tạm thời biến t.


Nếu FromT&, bạn sẽ có được một cái gì đó giống như

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

đó, tương tự như std::declval, là một giá trị trái: Khái niệm create<T&>() là/mang lại một giá trị trái, vì T& && (thông qua add_rvalue_reference) được thu gọn thành T&.

+0

Cảm ơn bạn đã tham khảo. Ngoài những gì bạn đã nói, có nhiều văn bản trực tiếp bên dưới phần nháp mà bạn trích dẫn, cụ thể là đề cập đến các vấn đề ngữ cảnh. Tôi sẽ chấp nhận điều này. Tôi đoán những gì còn lại là một câu hỏi kéo dài về việc liệu các tiêu chuẩn đang làm đúng. Những gì tôi không thích là, 'is_convertible' dường như không cần thiết gắn liền với khả năng truy cập constructor của' To', không liên quan gì đến 'From', hoặc quan hệ giữa' From' và 'To'. Tôi có thể tưởng tượng các tình huống mà tôi thực sự muốn biết liệu chuyển đổi có thể được thực hiện trong bối cảnh lựa chọn của tôi không ... –

+1

@MateiDavid 'is_convertible' cố gắng mô phỏng định nghĩa * chuyển đổi ngầm * mà tôi thấy không rõ ràng chút nào. Bản thân định nghĩa đó yêu cầu một nhà xây dựng sao chép/di chuyển có thể truy cập được. Có thể trong ngữ cảnh của bạn, 'is_constructible' có ý nghĩa hơn. – dyp

Các vấn đề liên quan