2017-10-05 13 views
19

Tôi đang cố gắng không cho phép một hoạt động cụ thể trên các loại biến động. Để thực hiện điều này tôi đang cố gắng sử dụng std::is_volatile, nhưng mã bên dưới được biên dịch mà không có lỗi, mà không phải là những gì tôi muốn.Làm thế nào để sử dụng std :: is_volatile?

Tại sao is_volatile::valuesai trong trường hợp dưới đây?

#include <type_traits> 

template<typename T> 
inline void DoStuff(T val) { 
    static_assert(!std::is_volatile<T>::value, "No volatile types plz"); 
    //... 
} 

int main() { 
    volatile char sometext[261]; 
    DoStuff(sometext); 
} 
+0

Đó chỉ là cách tính toán trích đối số mẫu - vòng loại không phải là một phần của các loại tham số giá trị được suy luận. Về cơ bản, nó giống như: 'volatile int src = ...; int n = src; '. Lưu ý cách 'n' không biết gì về trình độ của' src'. Nói cách khác, chuyển đổi lvalue-to-rvalue loại bỏ vòng loại. –

+0

@KerrekSB có thể bạn bỏ qua rằng một mảng được đưa ra như là đối số –

+0

@ M.M: Không, điều đó đơn thuần làm phức tạp các chi tiết một chút, nhưng vấn đề cốt lõi vẫn còn. –

Trả lời

28

Vấn đề là T không phải là một loại volatile ở tất cả. Đó là volatile char*. Chờ một phút, bạn nói, tôi thấy volatile ngay tại đó. Đúng, nhưng hãy xem xét điều này: char* volatile là một loại dễ bay hơi. volatile char* thì không. Đó là một con trỏ không bay hơi đến một mảng char dễ bay hơi.

Giải pháp: std::is_volatile<typename std::remove_pointer<T>::type>

+4

Giải pháp tốt hơn:' inline void DoStuff (T * val) '? Chấp nhận một 'T' sau đó tước con trỏ có vẻ ít hợp lý hơn là chấp nhận một' T * '. – Yakk

1

Bởi vì các hàm chấp nhận đối số của nó theo giá trị, cv-qualification của đối số gốc bị mất.

Chấp nhận nó bằng cách tham khảo:

void DoStuff(T& val) 
+0

Xem xét đối số ví dụ là một mảng, 'T * val' có thể có ý nghĩa hơn (nhưng chúng ta thiếu ngữ cảnh) – MSalters

9

Khi cố gắng để vượt qua mảng bằng giá trị, nó phân rã thành một con trỏ đến phần tử đầu tiên của nó.

Điều này có nghĩa là val thực sự là một int volatile *. Như vậy, nó trỏ đến một biến động int, nhưng bản thân nó không dễ bay hơi. Do đó, std::is_volatile trả về sai.

Bạn có thể thử tham gia mảng theo tham chiếu hoặc sử dụng std::remove_pointer.

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