2013-12-09 23 views
25

Tôi không hiểu tại sao mã này biên dịch mà không có lỗi:Trả lại khoảng trống?

#include <iostream> 

template <class T> 
struct Test 
{ 
    static constexpr T f() {return T();} 
}; 

int main() 
{ 
    Test<void> test; 
    test.f(); // Why not an error? 
    return 0; 
} 

Is it ok theo tiêu chuẩn, hoặc là nó một sự khoan dung biên dịch?

+0

Vâng, tôi biết bạn được phép có, nói, 'void foo() {} void bar() {return foo();}'. Tôi không chắc về điều này. – chris

+1

Câu hỏi của bạn, cụ thể là gì? Về việc trả về 'void' (trong đó, BTW, luôn luôn hợp pháp trong C++)? Hoặc về sự kết hợp 'constexpr void'? – AnT

+3

Có lẽ bạn nên giải thích những gì bạn nghĩ rằng lỗi nên được? –

Trả lời

24

này trông hợp lệ bởi draft C++11 standard, nếu chúng ta nhìn vào phần 5.2.3chuyển đổi loại Explicit (ký hiệu chức năng) đoạn nói (nhấn mạnh tôi):

The expression T(), where T is a simple-type-specifier or typename-specifier for a non-array complete object type or the (possibly cv-qualified) void type, creates a prvalue of the specified type, whose value is that produced by value-initializing (8.5) an object of type T; no initialization is done for the void() case.[...]

từ ngữ là khá tương tự pre C++11.

này ổn trong một constexpr mặc dù phần 7.1.5 đoạn 3 nói:

The definition of a constexpr function shall satisfy the following constraints:

và bao gồm đạn này:

its return type shall be a literal type;

trống không phải là một đen trong C++ 11 theo phần 3.9 đoạn , nhưng nếu chúng ta sau đó nhìn vào đoạn nó mang lại cho một ngoại lệ phù hợp với trường hợp này, nó nói:

If the instantiated template specialization of a constexpr function template or member function of a class template would fail to satisfy the requirements for a constexpr function or constexpr constructor, that specialization is not a constexpr function or constexpr constructor. [ Note: If the function is a member function it will still be const as described below. —end note ] If no specialization of the template would yield a constexpr function or constexpr constructor, the program is ill-formed; no diagnostic required.

Như Casey noted trong C++14 draft standardtrống là một đen, đây là phần 3.9Loại đoạn nói:

A type is a literal type if it is:

và bao gồm:

— void; or

6

Xem câu trả lời của @Shafik Yaghmour để biết thông tin đầy đủ.

Đoạn sau cấm này cho người không mẫu (7.1.5 (3)):

The definition of a constexpr function shall satisfy the following constraints:

  • [...]

  • its return type shall be a literal type or a reference to literal type

Xây dựng, một loại đen được định nghĩa trong 3.9 (10) như một loại vô hướng hoặc một phần của các đối tượng kiểu chữ trong một mảng hoặc cấu trúc. void không phải là một loại vô hướng theo 3.9 (9).

+1

* loại chữ * được định nghĩa trong 3.9/10; 'void' là * không * một kiểu chữ trong C++ 11. Tuy nhiên, trong C++ 14 (N3797), 'void' * được bao gồm trong các kiểu chữ. Vì vậy, mã của OP sẽ phù hợp với C++ 14. – Casey

+2

@Casey Ngoài ra tôi nghĩ 7.1.5 đoạn 6 cho phép điều này trong C++ 11 –

+1

@ShafikYaghmour Ahh, tôi đồng ý. Thú vị: mã này chuyên về hàm không phải 'constexpr' nhưng 'const' thành viên trong C++ 11 hoặc hàm thành viên' constexpr' và non-'const' trong C++ 14! – Casey

1

Chức năng của bạn trả về giá trị void(), bạn không quay trở lại từ một hàm void mỗi se. Bạn đang trả lại giá trị NULL. Những gì bạn đang làm tương đương với điều này:

void f() { return void(); } 

Điều này trả về giá trị void, giá trị khoảng trống duy nhất. bạn không thể trả lại bất cứ điều gì khác từ một hàm void vì nó sẽ là một kiểu khác.

+0

Tôi khá chắc chắn rằng điều này được cho phép trong C++ bởi 5.2.3 (2), mặc dù IANALL. – filmor

+0

Nó được cho phép bởi trình biên dịch, nhưng nó không thực sự hữu dụng vì nó không có giá trị gì cả. – user3084096

+2

Đây không phải là điểm khi nói về một tiêu chuẩn ngôn ngữ. – filmor

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