2016-06-23 18 views
7

Mã sau có được xác định rõ trong C++ không? (*)Con trỏ tới thành viên dữ liệu của loại không đầy đủ

Tôi đang gặp khó khăn trong việc tìm ra vị trí cần xem ngay cả tiêu chuẩn và tìm kiếm trên web chưa bật lên bất kỳ điều gì cụ thể.

struct S; 
struct T { 
    constexpr T() = default; 
    bool S::* a = nullptr; 
    int b  = 42; 
}; 
const T t{}; 
// Test. Compiled using: cl /W4 /WX /FAs filename.cpp 
#include <stdlib.h> 
int main() { 
    if (t.b != 42) abort(); 
} 

Lý do tôi hỏi là vì nó hoạt động (hoặc có vẻ) với các phiên bản mới hơn của GCC và Clang (x86/x86_64), nhưng thất bại (**) với Visual Studio 2015 Update 2 và cập nhật 3 RC.

Trước khi báo cáo lỗi, tôi muốn chắc chắn rằng tôi không dựa vào hành vi không xác định hoặc chỉ không tìm kiếm đúng cụm từ.

Tôi cũng đã thử sử dụng /vmg/vmb như được đề cập trong this post.

(*): Tôi chủ yếu quan tâm đến C++ 14 trở lên, nhưng tôi không thấy lý do nào mà câu trả lời sẽ không áp dụng cho C++ 11.
(**): Nếu mã được xác định rõ ràng, nó trông giống như một lỗi codegen, nơi nó không phải là phòng phân bổ cho con trỏ. Thay đổi struct S thành struct S{} dường như làm cho mã "hoạt động".

+1

Chính xác bạn đang mong đợi mã sẽ làm gì? 'T' có phải chứa một con trỏ tới' S' không, và nếu vậy, tại sao nó không được viết bằng 'S * a = nullptr;'? – Xirema

+0

Biên dịch [ở đây] (http://rextester.com/NFYP31324) và trên MSVS của riêng tôi năm 2015. Tôi có phiên bản 14.0.23107.0 D14REL – NathanOliver

+1

@Xirema: 'T :: a' là một [con trỏ đến dữ liệu (bool) thành viên] (http://en.cppreference.com/w/cpp/language/pointer#Pointers_to_data_members) trong loại không hoàn chỉnh 'S'. @NathanOliver: Nó cũng biên dịch cho tôi, nhưng nó 'hủy bỏ khi được thực hiện. – user786653

Trả lời

5

Mã của bạn được xác định rõ:

N4594 3,2/5

[...] Một kiểu lớp T phải đầy đủ nếu:

  • (5,1) đối tượng thuộc loại T được xác định (3.1) hoặc
  • (5.2) thành viên dữ liệu lớp không tĩnh thuộc loại T là khai báo ed (9.2), hoặc
  • (5,3) T được sử dụng như các loại đối tượng hoặc mảng kiểu phần tử trong một mới-biểu thức (5.3.4), hoặc
  • (5,4) một chuyển đổi giá trị trái-to-rvalue được áp dụng cho một glvalue đề cập đến một đối tượng kiểu T (4.1) hoặc
  • (5.5) một biểu thức được chuyển đổi (hoặc ngầm hoặc rõ ràng) để nhập T (khoản 4, 5.2.3, 5.2.7, 5.2 .9, 5.4) hoặc
  • (5.6) một biểu thức không phải là hằng số con trỏ null và có loại khác với cv void *, được chuyển thành con trỏ loại tới T hoặc tham chiếu đến T bằng cách sử dụng chuyển đổi chuẩn (Clau se 4), dynamic_cast (5.2.7) hoặc static_cast (5.2.9) hoặc
  • (5.7) toán tử truy cập thành viên lớp được áp dụng cho biểu thức loại T (5.2.5) hoặc
  • (5.8) toán tử typeid (5.2.8) hoặc toán tử sizeof (5.3.3) được áp dụng cho toán hạng kiểu T hoặc
  • (5.9) một hàm có kiểu trả về hoặc loại đối số loại T được xác định (3.1) hoặc được gọi là (5.2.2) hoặc
  • (5.10) một lớp có lớp cơ sở loại T được xác định (Điều 10) hoặc
  • (5.11) một giá trị của loại T được gán cho (5.18) hoặc
  • (5.12) loại T là đối tượng của biểu thức căn chỉnh (5.3.6) hoặc
  • (5.13) tuyên bố ngoại lệ có loại T, tham chiếu đến T hoặc trỏ tới T (15.3).

Không ai trong số họ nói rằng T cần phải được hoàn thiện để tuyên bố viên-con trỏ đến- của T.

+0

Cảm ơn! Tôi sẽ chấp nhận câu trả lời này trong một ngày hoặc lâu hơn trừ khi ai đó có thể tìm thấy những phát biểu phản đối ở đâu đó trong tiêu chuẩn. – user786653

+0

@ user786653 OK. – PcAF

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