2013-07-23 37 views
10

Trong một cuộc phỏng vấn xin việc, tôi được yêu cầu viết một metafunction xác định xem loại có phải là một con trỏ hay không. Đây là những gì tôi trình bày:Làm thế nào tôi có thể thực hiện xác nhận thời gian biên dịch mà không có C++ 11

template <typename T> 
struct is_pointer 
{ static const bool value = false; } 

template <typename T> 
struct is_pointer<T *> 
{ static const bool value = true; } 

Sau đó, tôi được yêu cầu viết một meta-khẳng định, rằng sẽ thất bại trong thời gian biên dịch nếu chức năng is_pointer tôi không phải là làm đúng.

Khi tôi sử dụng static_assert, anh ấy đã nói rõ ràng với tôi rằng Tôi chỉ có thể sử dụng tiêu chuẩn C++ 98. Làm thế nào tôi có thể đạt được điều này?

+8

Tôi nghĩ rằng vào thời điểm này bạn đã thông qua "kiểm tra để xem liệu bạn có thực sự biết ngôn ngữ "một phần của cuộc phỏng vấn hay không, trừ khi công ty tạo ra các trình biên dịch C++ hoặc một cái gì đó. –

Trả lời

5

Trong trường hợp của bạn

template <bool> struct assert; 
template <> struct assert<true> {}; 

sẽ giải quyết vấn đề:

assert<!is_pointer<char>::value>();  // valid 
assert<is_pointer<char *>::value>(); // valid 

assert<is_pointer<char>::value>();  // compilation error: 
             // use of incomplete class 
+0

Đó không phải là những gì SFINAE (giải pháp là ok, nhưng tên bị lạm dụng). –

+0

Điều này cũng bị giới hạn ở những vị trí mà bạn có thể tạo một đối tượng thuộc loại đó. Để có thể sử dụng nó trong các ngữ cảnh khác, bạn sẽ phải tạo các đối tượng giả: '// namespace: assert myassert; ' –

9

Có cách tiếp cận khác nhau, một trong những phổ biến cố typedef một kiểu không hợp lệ:

#define static_assert(condition) \ 
     typedef char assert ## __LINE__ [((condition)?1:-1)] 

này có thể được sử dụng trong hầu hết mọi ngữ cảnh và sẽ đi theo trình biên dịch nếu điều kiện là sai, vì nó sẽ cố gắng gõ một n loại không hợp lệ (mảng số phần tử âm). Nó có thể được sử dụng trong các ngữ cảnh khác nhau:

// namespace level: 
static_assert(sizeof(int)==4); 
struct type { 
    // class level: 
    static_assert(sizeof(int)==4); 
    void f() { 
     // function level 
     static_assert(sizeof(int)==4); 
    } 
}; 
+3

Điều này thậm chí có thể được sử dụng trong C thuần túy :) Nhưng lưu ý rằng với macro hiện tại, typedef sẽ luôn luôn là 'assert__LINE__', như là; để mở rộng '__LINE__' thành số dòng thực tế bạn cần một cuộc gọi macro" tham gia "trung gian: [Điều gì nên được thực hiện bằng các macro cần dán hai thẻ cùng nhau?] (http://www.parashift.com/c++-faq /macros-with-token-pasting.html) –

3

Tôi sẽ sử dụng BOOST_STATIC_ASSERT. Bạn có thể xem mã: boost/static_assert.hpp.

Dưới đây là một phiên bản rất đơn giản, chỉ cần cung cấp cho bạn một ý tưởng:

#define JOIN(X, Y) DO_JOIN(X, Y) 
#define DO_JOIN(X, Y) X ## Y 

template<bool cond> 
struct Static_assert_helper; // incomplete type 

template<> 
struct Static_assert_helper<true> { 
    typedef int Type; 
}; 

#define STATIC_ASSERT(cond) \ 
    typedef Static_assert_helper<(cond)>::Type JOIN(Static_assert_typedef_, __LINE__) 

Nó có thể được sử dụng ở nhiều nơi (xem tài liệu cho ví dụ).

(thực hiện Boost là hoàn thiện hơn, với ví dụ một sizeof và một struct trung gian, để đưa ra một thông báo lỗi tốt hơn và có thể di chuyển trên một loạt các trình biên dịch.)

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